Kubernetes

DRAFT

Principaux concepts

Configuration

Un ConfigMap est un objet qui contient des paires clé / valeur utilisable par les autres objets. L’objectif est d’isoler les valeurs qui dépendent de l’environnement.

apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-secret
data:
  POSTGRES_PASSWORD: admin-pwd
  POSTGRES_HOST_AUTH_METHOD: trust

Pour les données sensibles, on utilise plutôt un Secret.

apiVersion: v1
kind: Secret
metadata:
  name: citus-secrets
type: Opaque
data:
  password: cGFzc3dvcmQ=

Le mot de passe est encodé en base 64.

Type de secrets:

  • Opaque: (défaut)

  • kubernetes.io/service_account-token: (legacy)

  • kubernetes.io/dockercfg: pour l’accès à une registre d’images, avec un fichier ~/.dockercfg (ancien format)

  • kubernetes.io/dockerconfigjson: pour l’accès à une registre d’images, avec un fichier ~/.docker/config.json (nouveau format)

  • kubernetes.io/basic-auth

  • kubernetes.io/ssh-auth

  • kubernetes.io/tls

  • bootstrap.kubernetes.io/token

En production, on utilise un stockage externe des secrets.

Volumes

Un PersistentVolume est une ressource du cluster qui définit statiquement un mode de stockage.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: postgres-volume
spec:
  storageClassName: manual
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  hostPath:
    path: /data/postgresql

En réalité, les pods utilisent de PersistentVolumeClaims comme volumes. Ces derniers font le lien entre le pod et le persistent volume.

D’ailleurs, si le persistent volume n’a pas été déclaré, il est créé dynamiquement.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-volume-claim
  labels:
    app: postgres
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi

Un conteneur peut aussi monter un répertoire local comme volume.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: citus-master
spec:
  selector:
    matchLabels:
      app: citus-master
  replicas: 1
  template:
    metadata:
      labels:
        app: citus-master
    spec:
      containers:
      - name: citus-master
        image: citusdata/citus:11.1.4-pg14
        ports:
        - containerPort: 5432
        volumeMounts:
        - name: storage
          mountPath: /var/lib/postgresql/data
        - name: init-sql
          mountPath: /docker-entrypoint-initdb.d/init-master.sql
          readOnly: true
      volumes:
        - name: storage
          persistentVolumeClaim:
            claimName: citus-master-pvc
        - name: init-sql
          hostPath:
            path: /host/init-master.sql
            type: FileOrCreate

Pour que ça marche, il faut que le fichier soit présent sur la machine hôte de Kubernetes. Avec Minikube, il faut monter le répertoire /host.

~$ minikube mount $PWD:/host

Deployments

Un Service définit un moyen d’exposer une application dans le cluster. Il définit comment les pods sont accessibles. L’ensemble des pods associés dans le service sont définis par le selector.

apiVersion: v1
kind: Service
metadata:
  name: postgres
  labels:
    type: infra
    component: postgres
spec:
  type: NodePort
  ports:
    - port: 5432
  selector:
    run: postgres

Un service peut avoir les types suivants:

  • ClusterIP: (par défaut) il a une adresse IP interne au cluster, inaccessible de l’extérieur

  • NodePort: accessible depuis l’extérieur, en choisissant le port

  • LoadBalancer: loadbalancer accessible depuis l’extérieur

  • ExternalName: (pas bien compris) utilise un enregistrement DNS de type CNAME

~$ kubectl get services

L’attribut selector permet de spécifier le label des pods gérés par le service. Dans l’exemple ci-dessus, les pods qui ont le label run: postgres seront associés au service.

Un Deployment est l’object le plus concret. C’est à partir de lui que sont créés dynamiquement les conteneurs et les pods.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres
spec:
  replicas: 1
  selector:
    matchLabels:
      run: postgres
  template:
    metadata:
      labels:
        run: postgres
    spec:
      containers:
        - name: postgres
          image: 'postgres:14'
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 5432
          envFrom:
            - configMapRef:
                name: postgres-secret
          volumeMounts:
            - mountPath: /var/lib/postgresql/data
              name: postgresdata
      volumes:
        - name: postgresdata
          persistentVolumeClaim:
            claimName: postgres-volume-claim

Ingress Controller relaye le traffic entre l’extérieur et l’intérieur du cluster. Il y a 3 variantes: nginx, traeffik et HAProxy.

Eventuellement, il faut l’activer manuellement (exemple en local avec Minikube).

~$ minikube addons enable ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: postgres-ingress
spec:
  rules:
  - host: db.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: postgres-service
            port:
              number: 5432

RBAC

Nécessaire à SBA pour accéder à l’API

~$ kubectl create clusterrolebinding make-default-sa-cluster-admin \
                      --serviceaccount=default:default
                      --clusterrole=cluster-admin

Troubleshooting

~$ kubectl logs <podname>

Après un restart

~$ kubectl logs <podname> --previous
~$ kubectl describe pods <podname>
~$ kubectl exec <podname> -it -- sh

Pod de diagnostic DNS

apiVersion: v1
kind: Pod
metadata:
  name: dnsutils
  namespace: default
spec:
  containers:
  - name: dnsutils
    image: registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3
    command:
      - sleep
      - "infinity"
    imagePullPolicy: IfNotPresent
  restartPolicy: Always