enrialonso / k8s-curso

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Mini Curso k8s

k8s-logo

Fuentes

Documentacion oficial de k8s: AQUI

Review de la api de k8s: AQUI

Indice de contenido

Herramientas esenciales

Instalar kubectl link

En linux

Descargar el binario

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

Instalar

sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

Comprobar

kubectl version --client --output=yaml
Salida
clientVersion:
  buildDate: "2022-03-16T15:58:47Z"
  compiler: gc
  gitCommit: c285e781331a3785a7f436042c65c5641ce8a9e9
  gitTreeState: clean
  gitVersion: v1.23.5
  goVersion: go1.17.8
  major: "1"
  minor: "23"
  platform: linux/amd64

Instalar Minikube link

En linux

Descargar el binario

curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64

Instalar

sudo install minikube-linux-amd64 /usr/local/bin/minikube

Comprobar

minikube version
Salida
minikube version: v1.25.2
commit: 362d5fdc0a3dbee389b3d3f1034e8023e72bd3a7

Otras herramientas

No esenciales, pero está bueno conocer

Instalar kubecolor link

En linux
  • Descargar el binario - link
  • Descomprimir el binario
curl -LO https://github.com/hidetatz/kubecolor/releases/download/v0.0.20/kubecolor_0.0.20_Linux_x86_64.tar.gz
tar -xf kubecolor_0.0.20_Linux_x86_64.tar.gz kubecolor

Instalar

sudo install kubecolor /usr/local/bin/kubecolor

Comprobar

kubecolor version
Salida
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.5", GitCommit:"c285e781331a3785a7f436042c65c5641ce8a9e9", GitTreeState:"clean", BuildDate:"2022-03-16T15:58:47Z", GoVersion:"go1.17.8", Compiler:"gc", Platform:"linux/amd64"}

Configurar

En el fichero del profile para la terminal (ejemplo: ~/.bashrc) poner el alias

alias kubectl="kubecolor"

Lens Desktop - Un IDE para k8s - Link

En linux
  • Descargar el binario - link
curl -LO https://api.k8slens.dev/binaries/Lens-5.4.6-latest.20220428.1.amd64.deb

Instalar

sudo dpkg -i Lens-5.4.6-latest.20220428.1.amd64.deb

Comprobar

lens --version 

Manos a la obra

Cluster en local con minikube

La idea es montar un cluster en local y poder jugar con él aprendiendo los conceptos base. Para esto usaremos minikube y como interfase con el cluster usaremos kubectl.

minikube start

Este comando crea un cluster en local con el que podemos jugar, por defecto monta una máquina virtual con 2 cpus y 8 Gb de ram.

minikube dashboard

Con este comando abre en el navegador un dashboard web que está instalado por defecto en nuestro minikube para interactuar con el cluster y obtener informacion de nuestro cluster.

minikube-dashboard-localhost

minikube addons list

Lista todos los addons disponibles para minikube y podemos ver cuáles son los que están habilitados.

Salida
|-----------------------------|----------|--------------|--------------------------------|
|         ADDON NAME          | PROFILE  |    STATUS    |           MAINTAINER           |
|-----------------------------|----------|--------------|--------------------------------|
| ambassador                  | minikube | disabled     | third-party (ambassador)       |
| auto-pause                  | minikube | disabled     | google                         |
| csi-hostpath-driver         | minikube | disabled     | kubernetes                     |
| dashboard                   | minikube | enabled ✅   | kubernetes                     |
...

Conceptos basicos de Kubernetes

Kubernetes soporta múltiples clústeres virtuales respaldados por el mismo clúster físico. Estos clústeres virtuales se denominan namespaces. Puedes separar de forma logica las cargas de trabajo dentro del cluster. Existe algunos namespaces por defecto default por ejemplo.

k8s-namespaces

kubectl get namespaces
Salida
NAME                   STATUS   AGE
default                Active   47h
kube-node-lease        Active   47h
kube-public            Active   47h
kube-system            Active   47h
kubernetes-dashboard   Active   47h

Manifiesto de un namespace

apiVersion: v1
kind: Namespace
metadata:
  name: simple-namespace

Crear un namespace

kubectl apply -f ./files/simple-namespace.yaml

Borrar un namespace

kubectl delete namespace simple-namespace

Son las unidades más pequeñas que se pueden desplegar en k8s, es la forma que tiene k8s de agrupar uno o varios contenedores para las cargas de trabajo. Dentro de un pod pueden existir varios container, también se les pueden adjuntar volumenes o volumenes persistentes. Los contenedores dentro del pod comparten IP y dentro del pod la comunicación entre contenedores puedes realizarla con localhost.

kubectl get pod
Salida
NAME                     READY   STATUS    RESTARTS   AGE
nginx-85b98978db-hjf68   1/1     Running   0          55m

Comando crear pod

kubectl apply -f ./files/simple-pod.yaml

Comando estado del pod

kubectl get pod simple-pod -o wide

Comando borrar pod

kubectl delete pod simple-pod
Manifiesto de un pod
apiVersion: v1
kind: Pod
metadata:
  name: simple-pod
spec:
  containers:
  - name: nginx
    image: nginx:alpine

Es un tipo de controlador de k8s, es la unidad de más alto nivel que podemos gestionar en k8s. Nos permite definir diferentes funciones:

  • Control de réplicas
  • Escalabilidad de pods
  • Actualizaciones continuas
  • Despliegues automáticos
  • Rollback a versiones anteriores

La idea es manejar las cargas de trabajo basándonos en este controlador. Podemos definir el estado deseado y el agente kubelet se encarga de mantenerlo asi siempre

kubectl get deployment
Salida
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   1/1     1            1           65m

Ejemplo de manifiesto para un deployment

Manifiesto
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        resources:
          requests:
            memory: "64Mi"
            cpu: "200m"
          limits:
            memory: "128Mi"
            cpu: "500m"
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 10
        livenessProbe:
          tcpSocket:
            port: 80
          initialDelaySeconds: 15
          periodSeconds: 20
        ports:
        - containerPort: 80

Crear deployment

kubectl apply -f ./files/simple-deployment.yaml

Estado del deployment

kubectl get deployment nginx-deployment

Borrar deployment

kubectl delete deployment nginx-deployment

Es otro tipo de controlador de k8s y muy similar al deployment, pero no tiene réplicas, este controlador lo que hace es desplegar un pod por cada nodo que tenga el cluster, los casos de uso más frecuentes son:

  • Monitoreo de los nodos del cluster
  • Recolección de logs de los nodos del cluster
kubectl get daemonset
Salida
NAME               DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
nginx-deployment   1         1         0       1            0           <none>          4s

Ejemplo de manifiesto para un daemonset

Manifiesto
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        resources:
          requests:
            memory: "64Mi"
            cpu: "200m"
          limits:
            memory: "128Mi"
            cpu: "500m"
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 10
        livenessProbe:
          tcpSocket:
            port: 80
          initialDelaySeconds: 15
          periodSeconds: 20
        ports:
        - containerPort: 80

Crear daemonset

kubectl apply -f ./files/simple-daemonset.yaml

Estado del daemonset

kubectl get daemonset nginx-daemonset

Borrar daemonset

kubectl delete daemonset nginx-daemonset

También es una forma de crear pods, pero con un volumen asociado para mantener el estado, es decir que es como un deployment en el que cada pod tiene asociado un volumen de almacenamiento unico por pod en donde el pod y solo ese pod lo usa para mantener su estado, si el pod muere se crea otro pod y automáticamente este volumen se asocia al nuevo pod.

k8s-statefullset

kubectl get statefulset
Salida
NAME               DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
nginx-deployment   1         1         0       1            0           <none>          4s

Ejemplo de manifiesto para un daemonset

Manifiesto
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: simple-statefulset
spec:
  serviceName: nginx
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: k8s.gcr.io/nginx-slim:0.8
          ports:
            - containerPort: 80
              name: web
          volumeMounts:
            - name: www
              mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
    - metadata:
        name: www
      spec:
        accessModes: [ "ReadWriteOnce" ]
        resources:
          requests:
            storage: 1Gi

Crear statefulset

kubectl apply -f ./files/simple-statefulset.yaml

Estado del statefulset

kubectl get statefulset simple-statefulset

Borrar statefulset

kubectl delete statefulset simple-statefulset

Las comunicaciónes entre aplicaciones esta a la orden del dia, y es muy difícil encontrar una aplicacion hoy por hoy que no necesite comunicarse con el entorno que le rodea. Esto no es distinto dentro de un cluster, es más, de primeras complica más las cosas porque k8s va de compartir instancias o nodos entre cargas de trabajos, donde los pods pueden estar desplegados en distintos nodos y aun asi tiene que mantener la comunicación.

En esta parte de la documentacion oficial puedes tener más detalle.

En la imagen de arriba hay varias cosas que tenemos que tener en cuenta

  • Las ip de los nodos es distinta a la ip de los pods.
  • Cada pod tiene una IP.
  • Los containers dentro de un pod comparten la ip del pod que los contiene.
  • etcd es la base de datos de k8s y es donde se almacena y comparte el estado del cluster entre los nodos.
  • Los CNI o Container network interface, son agentes que corren en todos los nodos (workers en la imagen) en este caso calico
    • calico en un CNI que se encarga del manejo de las redes en el cluster, existen otros tipos de CNI, aqui los puedes conocer.
  • Las route-tables creadas por el agente de CNI en el caso de la imagen calico.
  • Toda la informacion de las route-tables se almacena en etcd.

En la imagen tenemos dos nodos con un pod en cada uno, si estos pods quieren comunicarse, el agente CNI almacenaria en etcd las route-tables para se pueda establecer la comunicación entre pods, cuando se crea un pod una de las primeras cosas que se hace es asignarle una ip, esto lo hace el agente del CNI, se almacena en etcd. También se borra esta configuración cuando sé borrar el pod, todo esto es trasparente para nosotros y lo hace el agente del CNI.

Articulos y videos destacados que hablan del tema


Es un objeto de la API de k8s en el que se define como conectarnos a los pods, básicamente un service lo que hace es agrupar lógicamente un conjunto de pods y definir una politica de entrada, de esta forma no tenemos que conocer la ip de los pods para comunicarnos. Existen distintos tipos de services, estos son los más comunes:

  • ClusterIP: expone una ip fija en el cluster. (Por defecto)
  • NodePort: expone un puerto en cada nodo.
  • LoadBalancer: crea un balanceador de carga (depende del proveedor de cloud que usemos) que redirecciona el tráfico a los pods.

⚠ no recomendado para entornos productivos

Este service se crea por defecto si no se define la etiqueta spec.type en el manifiesto, se mapea una ip interna del cluster con la ip de los pods, este mapeo se realiza con la definicion de un selector el cual debe estar presente en el manifiesto del service y del deployment, asi el service puede identificar y agrupar las ips de los pods para que puedan ser alcanzadas por la ip del cluster cuando hacemos una petition a esta.

Manifiesto de un service Cluster IP
# Manifiesto del service
apiVersion: v1
kind: Service
metadata:
  name: service-cluster-ip
spec:
  ports:
    - port: 80
      targetPort: 8080
  selector:
    role: role-cluster-ip <<< SELECTOR
# Manifiesto del deployment
...
spec:
  replicas: 3
  selector:
    matchLabels:
      role: role-cluster-ip <<< SELECTOR
...

Aplicar un deployment + service de tipo Cluster IP

kubectl apply -f "./files/service-cluster-ip.yaml"

Listar todo el cluster

kubectl get all -o wide

Si listamos todo el cluster podemos ver que estarían los pods creados por el deployment pod/app-service-cluster-ip... como también el service service/service-cluster-ip que estaba en el deployment (pudimos declarar el service en un manifiesto aparte también)

NAME                                          READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
pod/app-service-cluster-ip-67cd8b5645-4tgr4   1/1     Running   0          20s   172.17.0.7   minikube   <none>           <none>
pod/app-service-cluster-ip-67cd8b5645-9dxsw   1/1     Running   0          20s   172.17.0.5   minikube   <none>           <none>
pod/app-service-cluster-ip-67cd8b5645-sxxrj   1/1     Running   0          20s   172.17.0.6   minikube   <none>           <none>

NAME                         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE     SELECTOR
service/kubernetes           ClusterIP   10.96.0.1      <none>        443/TCP    5d19h   <none>
service/service-cluster-ip   ClusterIP   10.99.100.91   <none>        8080/TCP   20s     role=role-cluster-ip

Si describimos el service podemos encontrar más information

kubectl describe service service-cluster-ip
Salida
Name:              service-cluster-ip
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          role=role-cluster-ip
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.99.100.91
IPs:               10.99.100.91
Port:              <unset>  80/TCP
TargetPort:        8080/TCP
Endpoints:         172.17.0.5:8080,172.17.0.6:8080,172.17.0.7:8080
Session Affinity:  None
Events:            <none>

Para hacer peticiones a los pods solo podemos hacerlo desde dentro del cluster, para esto aplicamos un deployment con un pod. Desde ahi podemos hacer peticiones en a los pods de la app.

kubectl apply -f ./file/bastion.yaml

Nos metemos dentro del pod bastion

kubectl exec -it bastion -- sh

Con la terminal dentro del pod podemos hacer un curl [ip service]:[port service] y ver la respuesta de los pods, el service debería de balancear las peticiones entre los distintos pods.

curl 10.99.100.91:80
Hello, world!
Version: 1.0.0
Hostname: app-service-cluster-ip-67cd8b5645-sxxrj

También podemos hacer un curl al nombre del service service-cluster-ip

curl http://service-cluster-ip
Hello, world!
Version: 1.0.0
Hostname: app-service-cluster-ip-67cd8b5645-478tb

Este service expone un puerto en cada uno de los nodos del cluster y mapea el tráfico de ese puerto al service que agrupa los pods de nuestra aplicacion.

Manifiesto de un service Node Port

Nótese que a diferencia del manifiesto de cluster ip, node port tiene que tener spec.type igual a NodePort y para crear el puerto en cada uno de los nodos y que quede expuesto también la etiqueta spec.ports[].nodePort con el número del puerto que queremos exponer.

apiVersion: v1
kind: Service
metadata:
  name: service-node-port
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 30000
  selector:
    role: role-node-port <<< SELECTOR

Aplicar un deployment + service de tipo Node Port

kubectl apply -f "./files/service-node-port.yaml"

Ahora si queremos conectarnos por el service a los pods de la aplicacion debemos conocer la ip de los nodos del cluster

kubectl get nodes -o wide
NAME       STATUS   ROLES                  AGE     VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
minikube   Ready    control-plane,master   5d21h   v1.23.3   192.168.49.2   <none>        Ubuntu 20.04.2 LTS   5.15.0-33-generic   docker://20.10.12

También si usas minikube puedes correr el siguiente comando, devuelve la ip del nodo con el puerto del service que configuramos en el manifiesto. Puedes acceder desde el navegador o haciendo un curl.

minikube service service-node-port --url
___
http://192.168.49.2:30000

En este caso dependiendo de donde este montado el cluster cuando creamos un service de tipo load balancer crea algo similar a un node port, pero pone delante un loadbalancer para hacer de punto unico de entrada para los pods, si estamos en la nube creara un balanceador segun el proveedor de nube, en el caso de minikube se debe tener abierto una terminal corriendo un comando para que el service pueda tomar una ip y exponer los pods de la aplicacion.

Manifiesto de un service Load Balancer
apiVersion: v1
kind: Service
metadata:
  name: service-load-balancer
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 30000
  selector:
    role: role-load-balancer <<< SELECTOR

Si no configuramos la propiedad spec.ports[].nodePort k8s nos provee de un puerto que va desde 30000 al 32767.

Para crear un service de este tipo con minikube:

En una termina aparte ejecutamos el siguiente comando para levantar un tunnel y poder conectar al loadbalancer, dejaremos el comando ejecutando sin cerrar la terminal

minikube tunnel
Salida
...
Status: 
    machine: minikube
    pid: 125254
    route: 10.96.0.0/12 -> 192.168.49.2
    minikube: Running
    services: [service-load-balancer]
errors: 
    minikube: no errors
    router: no errors
    loadbalancer emulator: no errors
...

Aplicar el deployment en otra terminal

kubectl -apply -f ./files/service-load-balancer.yaml

Ahora si vemos que tenemos desplegado en el cluster deberíamos tener algo similar a esto

kubectl get all -o wide
NAME                                             READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
pod/app-service-load-balancer-57f56b48c8-7gbjq   1/1     Running   0          7s    172.17.0.7   minikube   <none>           <none>
pod/app-service-load-balancer-57f56b48c8-f6sbq   1/1     Running   0          7s    172.17.0.4   minikube   <none>           <none>
pod/app-service-load-balancer-57f56b48c8-p6mzq   1/1     Running   0          7s    172.17.0.3   minikube   <none>           <none>

NAME                            TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)        AGE    SELECTOR
service/kubernetes              ClusterIP      10.96.0.1        <none>           443/TCP        6d1h   <none>
service/service-load-balancer   LoadBalancer   10.105.169.212   10.105.169.212   80:30000/TCP   7s     role=role-load-balancer

Si copiamos la Ip externa del service/service-load-balancer y la abrimos en un navegador o hacemos un curl desde consola deberíamos poder llagar a los pods y balancear sobre ellos con distintas respuestas.

curl http://10.105.169.212
Hello, world!
Version: 1.0.0
Hostname: app-service-load-balancer-57f56b48c8-f6sbq

Es un tipo de controlador que permite al acceso a nuestras aplicaciones en k8s comunicarse con el exterior como unico punto de entrada, en donde podemos apuntar a distintas aplicaciones o deployments definiendo por ejemplo distintos paths en la url o reglas en el manifiesto del ingress.

Podemos decir que los ingress son una pieza externa y que debemos instalarla en el cluster, existen varios proveedores, dependiendo la naturaleza de nuestro cluster podremos usar uno u otro, en este enlace pueden ver algunos.

Un ingress debería ser capas de balancear carga en nuestras aplicaciones como también manejar conexiones SSL/TLS, la configuración puede variar segun el proveedor del ingress controler.

En la imagen se aprecia como funciona el acceso de un ingress a nuestras aplicaciones, el cliente hace una peticion al ingress el cual evalua las reglas de enrutamiento definidas en el manifiesto, estas reglas tienen asociado un service el cual a su vez tiene como target los pods del deployment de nuestras aplicacions.

Asi desde un unico punto de entrada se pueden hacer peticiones a distintas aplicaciones, con los services no podríamos hacer esto.

Manifiesto para un ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-app
spec:
  rules:
  - http:
      paths:
      - path: /v1
        pathType: Prefix
        backend:
          service:
            name: hello-v1
            port:
              number: 8080
      - path: /v2
        pathType: Prefix
        backend:
          service:
            name: hello-v2
            port:
              number: 8080

En la propiedad spec.rules[].http.paths[] es donde declaramos las distintas reglas para una conexion en este caso del tipo http.

Para minikube vamos a habilitar el ingress en los addons

minikube addons enable ingress

Verificamos que esta todo correcto

kubectl get pods -n ingress-nginx
NAME                                       READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-h9nvg       0/1     Completed   0          94s
ingress-nginx-admission-patch-4vk7d        0/1     Completed   1          94s
ingress-nginx-controller-cc8496874-lslb5   1/1     Running     0          94s

Aplicar el deployment con las dos aplicaciones y los dos services

kubectl apply -f files/deployment-for-ingress.yaml

Aplicar el controlador ingress que hagan target a los dos services creados

kubectl apply -f ./files/simple-ingress.yaml

Ahora podemos verificar el ingress y las reglas con este comando

kubectl describe ingress simple-ingress
Name:             simple-ingress
Labels:           <none>
Namespace:        default
Address:          192.168.49.2
Ingress Class:    nginx
Default backend:  <default>
Rules:
  Host        Path  Backends
  ----        ----  --------
  *           
              /v1   service-app-v1:8080 (172.17.0.11:8080,172.17.0.3:8080,172.17.0.7:8080)
              /v2   service-app-v2:8080 (172.17.0.10:8080,172.17.0.4:8080,172.17.0.8:8080)
Annotations:  <none>
Events:
  Type    Reason  Age                From                      Message
  ----    ------  ----               ----                      -------
  Normal  Sync    17m (x2 over 18m)  nginx-ingress-controller  Scheduled for sync

Ahora con la ip de nuestro cluster podríamos o bien hacer peticiones con el navegador o con curl para acceder a nuestras aplicaciones

minikube ip
curl http://http://192.168.49.2/v1
Hello, world!
Version: 1.0.0
Hostname: app-ingress-v1-64b5dffcd8-chbrp
curl http://http://192.168.49.2/v2
Hello, world!
Version: 2.0.0
Hostname: app-ingress-v2-6b68575fd9-jl9fz

Este objeto como su nombre lo indica almacena configuraciones que puedan ser consultadas por las aplicaciones, puedes leer los configmaps desde un deployment e inyectarlos en los pods como variables de entorno o como un volumen que inyecta un fichero de solo lectura para que los containers del pod lo usen.

Manifiesto configmap

apiVersion: v1
kind: ConfigMap
metadata:
  name: simple-configmap
data:
  dummy-var: dummy-value
  dummy-file-config: |
    dummy-var=dummy-value
Manifiesto del pod
apiVersion: v1
kind: Pod
metadata:
  name: pod-configmaps
spec:
  containers:
    - name: pod-configmaps
      image: alpine/curl
      args:
        - sleep
        - infinity
      env:
        - name: DUMMY_VAR
          valueFrom:
            configMapKeyRef:
              name: simple-configmap
              key: dummy-var
      volumeMounts:
        - name: config
          mountPath: "/config"
          readOnly: true
  volumes:
    - name: config
      configMap:
        name: simple-configmap
        items:
        - key: "dummy-file-config"
          path: "dummy-file-config"

Crear y aplicar un configmap

kubectl apply -f ./files/simple-configmap.yaml

Vamos a usarlo desde un pod con el siguiente manifiesto

kubectl apply -f ./files/pod-configmaps.yaml

Entramos al pod y verificamos las variables de entorno inyectadas y los ficheros en los volumenes

kubectl exec -it pod-configmaps -- env
...
DUMMY_VAR=dummy-value <<< configuración inyectada
...
kubectl exec -it pod-configmaps -- cat /config/dummy-file-config
dummy-var=dummy-value

⚠ Importante saber que si actualizas los valores del configmap, en el pod solo se actualizaran los ficheros del volumen, las variables de entorno seguirían siendo iguales. Para actualizar la configuración se debería matar el pod para que el deployment cre un pod nuevo y se mapeen los nuevos valores desde el configmap.

⚠ En caso de crear un pod y no existir él configmap saltarán errores y no se podría crear el pod.

...
MountVolume.SetUp failed for volume "config" : configmap "simple-configmap" not found
...
Error: configmap "simple-configmap" not found

Con este objeto crearemos secretos que van a poder ser usados por nuestros pod, algo asi como los configmaps, pero los valores de las variables esta vez están codificados en base64, estos valores son faciles de descodificar y no se recomienda guardar credenciales sensibles.

Manifiesto

apiVersion: v1
kind: Secret
metadata:
  name: simple-secrets
type: Opaque
data:
  username: YWRtaW4=
  password: c3VwM3JwYXNzdzByZAo=

Crear un secret desde un manifiesto

kubectl apply -f ./files/simple-secrets.yaml

También podemos crear el secret con kubectl con el siguiente comando

kubectl create secret generic simple-secrets \
  --from-literal=username=admin \
  --from-literal=password=superpassword
Manifiesto del pod consumiendo secrets
apiVersion: v1
kind: Pod
metadata:
  name: pod-secrets
spec:
  containers:
    - name: pod-secrets
      image: alpine/curl
      args:
        - sleep
        - infinity
      env:
        - name: USERNAME
          valueFrom:
            secretMapKeyRef:
              name: simple-secrets
              key: username
        - name: PASSWORD
            valueFrom:
              secretMapKeyRef:
                name: simple-secrets
                key: password

Crear pod que lee los secrets

kubectl apply -f ./files/pod-secrets.yaml

Verificar si las variables de entorno están dentro del pod

kubectl exec -it pod-secrets -- env

About