Ce document décrit l’installation d’ArgoCD sur Kubernetes / OpenShift, puis comment utiliser ArgoCD.
Les images d’argoCD sont disponibles sur Internet, il faut au préalable les importer dans notre infrastructure. A la rédaction du document, les images suivantes sont requises :
NB: Le plugin argocd-vault-plugin est inclu dans le déploiement
Se connecter sur ast-srv-097, puis télécharger les images :
ssh ast-srv-097
docker_image_fetcher quay.io/argoproj/argocd:v2.4.12
docker_image_fetcher ghcr.io/dexidp/dex:v2.32.0
docker_image_fetcher docker.io/redis:7.0.4-alpine
Commencer par récupérer les binaires sur la machine d’infrastructure
ssh ast-srv-097
su -
file-repo-fetcher https://github.com/argoproj-labs/argocd-vault-plugin/releases/download/v1.11.0/argocd-vault-plugin_1.11.0_linux_amd64
file-repo-fetcher https://github.com/argoproj/argo-cd/releases/download/v2.5.0/argocd-linux-amd64
Installation d’ArgoCD
Modifier
NB: Remplacer asten–argocd–prod par le namespace choisi Remplacer 10.26.128.1 par l’adresse IP allouée
Etape 1 - namespace
Créer un namespace qui contiendra ArgoCD
kubectl create ns asten–argocd–prod
Etape 2 - CustomResourceDefinition
Déclarer les CRDs qui sont présent dans CRDs
cd CRDs
scp * admin-sno@k8s01-master:/tmp
ssh admin-sno@k8s01-master
sudo bash
cd /tmp
kubectl apply -f .
Etape 3 - Rbac
Appliquer les rbac, commencer par changer le namespace
cd RBAC
cp rbac.yaml.tmpl rbac.yaml
sed -i ‹ s/NAMESPACE/asten–argocd–prod/g › rbac.yaml
Appliquer les rbac
scp rbac.yaml admin-sno@k8s01-master:/tmp
ssh admin-sno@k8s01-master
sudo bash
cd /tmp
kubectl apply -f rbac.yaml
NB: Les étapes 4 à 9 sont faites via le script ./install
Etapes 4 à 9
Le script ./install effectue les actions suivantes : - Prise en compte des paramètres - Copie des fichier .tmpl vers .yaml avec recherche/remplace du namespace et de l’adresse IP - kubectl apply des yaml générés
./install
Nom du namespace : asten–argocd–prod
Adresse IP externe : 10.26.254.1
Passer à l’étape 10 {.is-info}
Etape 4 - ServiceAccount
Modifier le namespace
cp 01-accounts.yaml.tmpl 01-accounts.yaml
sed -i ‹ s/NAMESPACE/asten–argocd–prod/g › 01-accounts.yaml
Créer les utilisateurs de service
scp 01-accounts.yaml admin-sno@k8s01-master:/tmp
ssh admin-sno@k8s01-master
sudo bash
cd /tmp
kubectl apply -f 01-accounts.yaml
Etape 5 - configMap
Modifier le namespace, puis créer les configMaps
cp 02-configMap.yaml.tmpl 02-configMap.yaml
sed -i ‹ s/NAMESPACE/asten–argocd–prod/g › 02-configMap.yaml
kubectl apply -f 02-configMap.yaml
Etape 6 - secrets
Modifier le namespace, puis créer les secrets
cp 03-secrets.yaml.tmpl 03-secrets.yaml
sed -i ‹ s/NAMESPACE/asten–argocd–prod/g › 03-secrets.yaml
kubectl apply -f 03-secrets.yaml
Etape 7 - services
Modifier le namespace, puis créer les services
cp 04-services.yaml.tmpl 04-services.yaml
sed -i ‹ s/NAMESPACE/asten–argocd–prod/g › 04-services.yaml
sed -i ‹ s/EXTERNALIP/10.26.128.1/g › 04-services.yaml
kubectl apply -f 04-services.yaml
Etape 8 - deployment
Modifier le namespace, puis créer les deployment
cp 05-deployment.yaml.tmpl 05-deployment.yaml
sed -i ‹ s/NAMESPACE/asten–argocd–prod/g › 05-deployment.yaml
kubectl apply -f 05-deployment.yaml
Etape 9 - statefulset
Modifier le namespace, puis créer le statefulset
cp 06-statefullset.yaml.tmpl 06-statefullset.yaml
sed -i ‹ s/NAMESPACE/asten–argocd–prod/g › 06-statefullset.yaml
kubectl apply -f 06-statefullset.yaml
Etape 9 - networkpolicies
Modifier le namespace, puis créer les networkpolicies
cp 07-networkpolicies.yaml.tmpl 07-networkpolicies.yaml
sed -i ‹ s/NAMESPACE/asten–argocd–prod/g › 07-networkpolicies.yaml
kubectl apply -f 07-networkpolicies.yaml
Etape 10 - Validation
Avant de continuer, il faut vérifier que l’application fonctionne bien
k get all
NAME READY STATUS RESTARTS AGE
pod/argocd-application-controller-0 1/1 Running 0 28m
pod/argocd-applicationset-controller-5f48c56d4c-kbgp9 1/1 Running 0 28m
pod/argocd-dex-server-986f685c6-6hclw 1/1 Running 0 28m
pod/argocd-notifications-controller-5855d59bc7-v2c9f 1/1 Running 0 28m
pod/argocd-redis-58886864b6-6gzd2 1/1 Running 0 28m
pod/argocd-repo-server-78fc9f9655-s8p4m 1/1 Running 0 28m
pod/argocd-server-5ccf56989c-t5lkq 1/1 Running 0 28m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/argocd--external-ip ClusterIP 10.26.193.252 10.26.254.1 80/TCP,443/TCP 19h
service/argocd-applicationset-controller ClusterIP 10.26.58.183 <none> 7000/TCP,8080/TCP 19h
service/argocd-dex-server ClusterIP 10.26.19.221 <none> 5556/TCP,5557/TCP,5558/TCP 19h
service/argocd-metrics ClusterIP 10.26.102.100 <none> 8082/TCP 19h
service/argocd-notifications-controller-metrics ClusterIP 10.26.30.182 <none> 9001/TCP 19h
service/argocd-redis ClusterIP 10.26.221.106 <none> 6379/TCP 19h
service/argocd-repo-server ClusterIP 10.26.96.83 <none> 8081/TCP,8084/TCP 19h
service/argocd-server-metrics ClusterIP 10.26.36.244 <none> 8083/TCP 19h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/argocd-applicationset-controller 1/1 1 1 28m
deployment.apps/argocd-dex-server 1/1 1 1 28m
deployment.apps/argocd-notifications-controller 1/1 1 1 28m
deployment.apps/argocd-redis 1/1 1 1 28m
deployment.apps/argocd-repo-server 1/1 1 1 28m
deployment.apps/argocd-server 1/1 1 1 28m
NAME DESIRED CURRENT READY AGE
replicaset.apps/argocd-applicationset-controller-5f48c56d4c 1 1 1 28m
replicaset.apps/argocd-dex-server-986f685c6 1 1 1 28m
replicaset.apps/argocd-notifications-controller-5855d59bc7 1 1 1 28m
replicaset.apps/argocd-redis-58886864b6 1 1 1 28m
replicaset.apps/argocd-repo-server-78fc9f9655 1 1 1 28m
replicaset.apps/argocd-server-5ccf56989c 1 1 1 28m
NAME READY AGE
statefulset.apps/argocd-application-controller 1/1 28m
Etape 11 - Première connection
Pour se connecter, il est nécessaire de disposer du mot de passe admin
k get secret
NAME TYPE DATA AGE
argocd-initial-admin-secret Opaque 1 76m
argocd-notifications-secret Opaque 0 20h
argocd-secret Opaque 3 20h
kubectl get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
Se connecter avec admin et le mot de passe affiché.
argo-login.png
ArgoCD est fonctionnel !
Installer argocd cli
curl -sSL -o argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd
rm argocd-linux-amd64
A. Modifier le configMap argocd-cm
k edit cm argocd-cm
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app.kubernetes.io/name: argocd-cm
app.kubernetes.io/part-of: argocd
name: argocd-cm
namespace: asten--argocd--prod
data:
accounts.admin-gbn: apiKey, login
accounts.admin-sno: apiKey, login
accounts.admin-ebd: apiKey, login
accounts.admin-mhu: apiKey, login
NB: Penser à sauvegarder le configMap sous forme de fichier, sous vi :w argocd-cm.yaml
B. Donner un rôle à l’utilisateur
k edit cm argocd-rbac-cm
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app.kubernetes.io/name: argocd-rbac-cm
app.kubernetes.io/part-of: argocd
name: argocd-rbac-cm
namespace: asten–argocd–prod
data:
policy.csv: |
p, role:org-admin, applications, ., ./., allow
p, role:org-admin, exec, create, ./., allow
p, role:org-admin, clusters, get, ., allow
p, role:org-admin, clusters, create, ., allow
p, role:org-admin, clusters, update, ., allow
p, role:org-admin, clusters, delete, ., allow
p, role:org-admin, projects, get, ., allow
p, role:org-admin, projects, create, ., allow
p, role:org-admin, projects, update, ., allow
p, role:org-admin, projects, delete, ., allow
p, role:org-admin, repositories, get, ., allow
p, role:org-admin, repositories, create, ., allow
p, role:org-admin, repositories, update, ., allow
p, role:org-admin, repositories, delete, ., allow
p, role:org-admin, accounts, update, ., allow
g, admin-sno, role:org-admin
g, admin-gbn, role:org-admin
g, admin-mhu, role:org-admin
g, admin-ebd, role:org-admin
policy.default: role:‹ ›
policy.matchMode: regex
Note : on utilise la notation en regex pour plus de flexibilité sur l’attribution des droits en fonction des resources.
C. Créer un mot de passe
Il faut utiliser le client argocd sur le master pour changer le mot de passe
NB: Utiliser le compte admin-xxx
kubectl get svc -n asten--argocd--prod
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
argocd--external-ip ClusterIP 10.26.193.252 10.26.139.2 80/TCP,443/TCP 26h
argocd--nodeport NodePort 10.26.153.154 <none> 80:30462/TCP,443:30901/TCP 4m
argocd-applicationset-controller ClusterIP 10.26.58.183 <none> 7000/TCP,8080/TCP 26h
argocd-dex-server ClusterIP 10.26.19.221 <none> 5556/TCP,5557/TCP,5558/TCP 26h
argocd-metrics ClusterIP 10.26.102.100 <none> 8082/TCP 26h
argocd-notifications-controller-metrics ClusterIP 10.26.30.182 <none> 9001/TCP 26h
argocd-redis ClusterIP 10.26.221.106 <none> 6379/TCP 26h
argocd-repo-server ClusterIP 10.26.96.83 <none> 8081/TCP,8084/TCP 26h
argocd-server-metrics ClusterIP 10.26.36.244 <none> 8083/TCP 26h
Lire le port associé
argocd login localhost:30901 --username admin --grpc-web-root-path /
argocd account list
argocd account update-password --account admin-sno --new-password **************
*** Enter password of currently logged in user (admin):
Password updated
NB: le mot de passe est en clair sur la ligne de commande
Il reste à désactiver le compte admin dans argocd-cm en ajoutant
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app.kubernetes.io/name: argocd-cm
app.kubernetes.io/part-of: argocd
name: argocd-cm
namespace: asten--argocd--prod
data:
admin.enabled: "false"
accounts.admin-gbn: apiKey, login
accounts.admin-sno: apiKey, login
accounts.admin-ebd: apiKey, login
accounts.admin-mhu: apiKey, login
Installer le plugin consiste à :
On pourrait modifier l’image du conteneur pour embarquer le binaire, mais nous préférons utiliser un initcontainer :
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/component: repo-server
app.kubernetes.io/name: argocd-repo-server
app.kubernetes.io/part-of: argocd
name: argocd-repo-server
namespace: cluster-infra--argocd--prod
spec:
template:
spec:
initContainers:
- name: download-tools
image: docker-registry.mut.p10s.asten/library/alpine:3.16
env:
- name: AVP_VERSION
value: 1.11.0
command: [sh, -c]
args:
- >-
wget --no-check-certificate https://file-repo.mut.p10s.asten/github.com/argoproj-labs/argocd-vault-plugin/releases/download/v${AVP_VERSION}/argocd-vault-plugin_${AVP_VERSION}_linux_amd64 -O /custom-tools/argocd-vault-plugin &&
chmod a+rx /custom-tools/argocd-vault-plugin
volumeMounts:
- mountPath: /custom-tools
name: custom-tools
Le principe est simple : on définit un plugin en fournissant un nom (ce qui définit le nom avec lequel le plugin sera accessible), et une commande devant retourner dans le stdout l’ensemble des manifestes au format yaml.
On pourrait par exemple faire un helm template …
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: cluster-infra--argocd--prod
labels:
app.kubernetes.io/name: argocd-cm
app.kubernetes.io/part-of: argocd
data:
# ...
configManagementPlugins: |
- name: vault
generate:
command: ["/bin/sh", "-c"]
args: ["cat manifests.yaml | argocd-vault-plugin generate -"]
# ...
Le plugin doit pouvoir se connecter au vault pour y lire les secrets.
On utilise la méthode d’authentification “k8s” qui se base sur les serviceaccount du cluster k8s.
Dans un premier temps, on active cette méthode d’authentification côté vault :
vault auth enable kubernetes
On configure la méthode pour qu’elle puisse interroger l’API k8s :
vault write auth/kubernetes/config \
kubernetes_host=https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT
Note: pas besoin de configurer de token ou de certificat : vault sait maintenant lire dynamiquement le certificat du cluster et le token du serviceaccount utilisé parle pod (et c’est une bonne nouvelle car celui-ci est renouvelé périodiquement).
Le serviceaccount utilisé par le pod du vault doit avoir le droit d’utiliser l’API “auth-delegator” de kubernetes pour vérifier l’identité des serviceaccounts qui le contactent. Pour cela, il faut mettre en place un ClusterRoleBinding :
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: vault-server-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: vault
namespace: cluster-infra--hvault--prod
On créé un role pour argocd en précisant qu’il se connecte en utilisant le service account “argocd-repo-server” du namespace “cluster-infra–argocd–prod” et qu’on veut l’associer à la policy “argocd”:
vault write auth/kubernetes/role/argocd \
bound_service_account_names=argocd-repo-server \
bound_service_account_namespaces=cluster-infra--argocd--prod \
policies=argocd \
ttl=1h
On créé la policy : argocd doit pouvoir lire tous les secrets :
vault policy write argocd -<<EOF
path "secret/data/*" {
capabilities = [ "read" ]
}
EOF