Kubernetes


Buenas tardes Gente, En el dia de hoy les voy a contar que es Kubernetes y como podemos utilizarlo para obtener una mejor portabilidad de sus aplicaciones, para los que nunca escucharon nombrar Kubernetes esta es una tecnologia confiable de google la cual es utilizada para mantener sus aplicaciones , es una plataforma la cual utiliza un motor de contenedores que puede ser docker/openshift entre otros.

Kubernetes: Ezequiel Arielli


1- Introducción a Kubernetes.
2- Componentes de Kubernetes.
3- Elementos del Cluster,Demonios y Arquitectura.
4- Redes en Kubernetes.
5- Desplegando Cluster de Kubernetes en Centos 7 Bare-Metal .
6- Configurando Kubedns y Kubedashboard.
7- Configurando Monitoreo con Grafanna/Heapterz/InFluxdb.
8- Instalando Storage-NFS Centos 7 y Configuración de almacenamiento persistente.
9- Deploy Aplicación en Kubernetes.
10- Publicando Servicio APP.



1- Introducción a Kubernetes:


Kubernetes:

Es una plataforma para orquestaciòn de contenedores la cual corre dentro de un Cluster de Servidores que puede ser montando en nubes publicas, privadas,hybridas y multi-cloud.

Kubernetes utiliza a docker como motor a la hora de desplegar los contenedores, tambien es compatible con Openshift y otros motores de containers.

Kubernetes nos permite realizar despliegue de aplicaciones que pueden ser escaladas y administradas de forma muy facil y eficiente.

Una de las principales ventajas de Kubernetes es que nos añade gran portabilidad en caso de tener que migrar la aplicaciòn a un ambiente distinto(hybrid,cloud,etc)

Existen varios tipos y formas de correr Kubernetes ya sea como un servicio en Google Cloud el cual ya nos ofrece un cluster completamente configurado, o instalando el cluster manualmente en multiples sistemas operativos Linux(Centos,Core OS, Debian,etc).


2- Componentes de Kubernetes:


Cluster: Grupo de servidores el cual agrupa la capacidad de Computo(procesamiento, memoria,etc).El cluster se puede generar en ambientes de tipo Cloud/Hybrid/Private.


Pods: Son los contenedores de nuestro motor docker/openshift/etc. Administrados y programados por kubernetes. Una de sus caracteristicas es que soportan volumenes persistentes al igual que docker.


Replication controllers: Administra el ciclo de vida de los pods y replicas programadas .
En caso de fallo de un nodo de nuestro cluster, el servidor Master le avisa al demonio de replicatiòn controller que este cayo y en caso de ser requerido nos deployara pods en otro nodo.


Services: Es el microservicio de una aplicaciòn la cual fue deployada en un pod o Replication Controller y se puede conectar a otro servicio para Lograr la aplicaciòn final.

Un ejemplo de esto puede ser un replicatiòn controller llamado WordPress(nos realiza un deploy de 3 containers/pod), el cual es asociado a un servicio con el mismo nombre y se conecta al replication controller a traves de un Label/Etiqueta.

Este servicio llamado WordPress ,lo podemos conectar a otro servicio llamado MYSQL(Mismo proceso que WordPress con el Replication Controller).


Labels: Son utilizados para organizar y seleccionar un grupo de objetos basado en pares del tipo key:value.

Labels son fundamentales para conectar los servicios a los replication controllers , pods.


Deployments: Es utilizado para realizar el deploy de una app y este se encargara de generarnos el replication controller y monitorearlo (El replication controller luego nos creara los pods requeridos).


3- Elementos del Cluster,Demonios y Arquitectura:


Kubernetes Master:

El master de kubernetes es el encargado de monitorear el estado de los Nodos, Servicios y Aplicaciones del Cluster. A continuación se detallan los demonios que lo ayudan a obtener esta información.


Etcd:
Es el servicio de disponibilidad de cluster desarrollado por CoreOS y utilizado tambien por Centos/REDHAT, otro servicio de cluster es Zookeeper que es utilizado por Apache Mesos.
El demonio etcd es el encargado del almacenamiento distribuido.
Utiliza una llave/valor que puede ser distribuida y leida por multiples nodos.
Kubernetes utiliza etcd para guardar la configuraciòn y el estado del cluster leyendo la metadata de de los nodos.


API server:
API Server de Kubernetes se encarga de validar y configurar los datos de los objetos api que incluyen los pods, servicios, replication controllers,etc.
El servidor de API sirve para operaciones REST y proporciona al frontend el estado compartido del clúster a través del cual interactúan todos los demás componentes.


Controller Manager Server:
Es un servicio usado para manejar el proceso de replicación de las tareas definidas.
Los detalles de estas operaciones son escritos en el etcd, donde el controller
manager observa los cambios y cuanto un cambio es detectado, el controller manager lee la nueva
información y ejecuta el proceso de replicacion hasta alcanzar el estado deseado.


Scheduler Server: Es el servicio que se encarga balancear la carga de los servidores y elegir el nodo mas saludable(procesamiento, memoria,etc) a la hora de deployar un pod.
Tambien se utiliza para leer los requisitos de un pod, analizar el ambiente del cluster y seleccionar el nodo más performante.
Este servicio adicionalmente cumple la función de monitorear el estado de los recursos de los nodos en realtime.


Kubernetes Minion:

Un minión es un nodo/servidor que forma parte de un Cluster, este nos aporta su Computo(procesamiento,memoria,etc) y los suma a los recursos del Cluster.
Para poder lograr esto el minion utiliza los siguientes demonios que lo mantienen en contacto con el Master.


Kubelet: Este servicio se encarga de obtener las instrucciones del Master y realizar los cambios correspodientes dentro del nodo.
Otra de sus funcion es manejar la creación y configuración de los pods(imagenes,volumenes,etc).


Kube-Proxy: Este servicio monitorea los Servicios y Endpoints levantandos en el master.
Nos provee la apertura de un puerto especifico/aleatorio en el pod para que pueda ser accedido y configura las reglas de firewalls requeridas.


Arquitectura de Kubernetes:



4- Redes en Kubernetes:


Flannel: Flannel es un tipo de red overlay, se encarga que los contenedores desplagos bajo el cluster de Kubernetes tendrán una IP de un mismo rango para poder comunicarse entre si.
Existen otros tipos de clientes para generar redes en Kubernetes para los contenedores como lo son Calico y Weave.
Tengo que destacar que Flannel al dia de hoy es uno de los mecanismo de red overlay más utilizado.


Red de Cluster: Es la red virtual generada por Kubernetes la cual asigna un rango de red especifico a los servicios desplegados en el Cluster para que sean interconectados.


Red Fisica: Es la red donde que se utiliza para conectar un master,nodos y almacenamientos isci,etc.


5- Desplegando Cluster de Kubernetes en Centos 7 Bare-Metal


Cluster Configuración:


Master: 172.16.0.1
Minion1: 172.16.0.2
Minion2: 172.16.0.3
storage-nfs: 172.16.0.50

Redes del Cluster y Servicio DNS:


Red de Infraestuctura Privada/Local: 172.16.0.0/16


Red Flannel para los Contenedores: 172.30.0.0/16 (Cada uno puede crear el rango deseado)


Red de Cluster de Servicios Kubernetes: 10.254.0.0/16 (Cada uno puede crear el rango deseado)


IP del Servicio Kubernetes / GW : 10.254.0.1 (IP encargada del Servicio de Cluster de Kubernetes- Gateway)


IP del DNS de Kubernetes : 10.254.3.100 (Actua como DNS para los servicios de Cluster – IP a elección)


Instalando el Master de Kubernetes:


setenforce 0
systemctl stop firewalld
systemctl disable firewalld
yum -y install ntp
systemctl start ntpd
systemctl enable ntpd
yum update -y
echo "172.16.0.1 Master
172.16.0.2 Minion1
172.16.0.3 Minion2
172.16.0.50 storage-nfs" >> /etc/hosts
yum -y install etcd kubernetes flannel

Configuramos ETCD


vi /etc/etcd/etcd.conf

ETCD_NAME=default
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://0.0.0.0:2379"

Generando Certificado de Seguridad para autenticación del API Request.


Link del script en github para generar certificado:


https://github.com/kubernetes/kubernetes/blob/master/cluster/saltbase/salt/generate-cert/make-ca-cert.sh


En la linea 30 debemos editar el grupo y la cuenta de Kubernetes en mi caso sera root.


Debemos modificar CERT_GROUP con nuestro usuario/grupo.
29 cert_dir=${CERT_DIR:-/srv/kubernetes}
30 cert_group=${CERT_GROUP:-kube}

Ejemplo:


wget https://github.com/kubernetes/kubernetes/blob/master/cluster/saltbase/salt/generate-cert/make-ca-cert.sh
vi make-ca-cert.sh
29 cert_dir=${CERT_DIR:-/srv/kubernetes}
30 cert_group=${root:-kube}

Finalizando la edición ejecutamos el script de la siguiente manera indicando nuestras redes y IP del Cluster.


bash make-ca-cert.sh "172.16.0.1" "IP:172.16.0.1,IP:10.254.0.1,DNS:kubernetes,DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.cluster.local"

Configuramos el APISERVER


vi /etc/kubernetes/apiserver

# Bind kube API server to this IP
KUBE_API_ADDRESS="--address=0.0.0.0"
# Port that kube api server listens to.
KUBE_API_PORT="--port=8080"
# Port kubelet listen on
KUBELET_PORT="--kubelet-port=10250"
# Address range to use for services(Work unit of Kubernetes)
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"
# default admission control policies
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"
# Add your own!
KUBE_API_ARGS="--client-ca-file=/srv/kubernetes/ca.crt --tls-cert-file=/srv/kubernetes/server.cert --tls-private-key-file=/srv/kubernetes/server.key"

Configuramos el CONFIG de Kubernetes


vi /etc/kubernetes/config

# Comma separated list of nodes running etcd cluster
KUBE_ETCD_SERVERS="--etcd-servers=http://172.16.0.1:2379"
# Logging will be stored in system journal
KUBE_LOGTOSTDERR="--logtostderr=true"
# Journal message level, 0 is debug
KUBE_LOG_LEVEL="--v=0"
# Should this cluster be allowed to run privileged docker containers
KUBE_ALLOW_PRIV="--allow-privileged=false"
# Api-server endpoint used in scheduler and controller-manager
KUBE_MASTER="--master=http://172.16.0.1:8080"

Configuramos el Controller Manager de Kubernetes con nuestro certificado


vi /etc/kubernetes/controller-manager

# Add your own!
KUBE_CONTROLLER_MANAGER_ARGS="--root-ca-file=/srv/kubernetes/ca.crt --service-account-private-key-file=/srv/kubernetes/server.key"

Generamos la Red Flannel en el Master


systemctl start etcd
etcdctl mkdir /kube-centos/network
etcdctl mk /kube-centos/network/config "{ \"Network\": \"172.30.0.0/16\", \"SubnetLen\": 24, \"Backend\": { \"Type\": \"vxlan\" } }"

Configuramos la red Flannel en el Master


vi /etc/sysconfig/flanneld

# Flanneld configuration options

# etcd url location. Point this to the server where etcd runs

FLANNEL_ETCD_ENDPOINTS="http://127.0.0.1:2379"

FLANNEL_ETCD="http://172.16.0.1:2379"

# etcd config key. This is the configuration key that flannel queries
# For address range assignment
#FLANNEL_ETCD_PREFIX="/atomic.io/network"

FLANNEL_ETCD_PREFIX="/kube-centos/network"

# Any additional options that you want to pass

FLANNEL_OPTIONS=""

REINICIAMOS LOS SERVICIOS DEL MASTER


for SERVICES in etcd kube-apiserver kube-controller-manager kube-scheduler flanneld; do
systemctl restart $SERVICES
systemctl enable $SERVICES
systemctl status $SERVICES
done

Instalando Minion1 en Kubernetes:


setenforce 0
systemctl stop firewalld
systemctl disable firewalld
yum -y install ntp
systemctl start ntpd
systemctl enable ntpd
yum update -y
echo "172.16.0.1 Master
172.16.0.2 Minion1
172.16.0.3 Minion2
172.16.0.50 storage-nfs" >> /etc/hosts
yum -y install kubernetes flannel

Configuramos la red Flannel en el Minion1


vi /etc/sysconfig/flanneld

# etcd URL location. Point this to the server where etcd runs
FLANNEL_ETCD="http://172.16.0.1:2379"
# etcd config key. This is the configuration key that flannel queries
# For address range assignment
FLANNEL_ETCD_PREFIX="/kube-centos/network"
# Any additional options that you want to pass
FLANNEL_OPTIONS=""


Configuramos servicio de Kubelet en el Minion1


vi /etc/kubernetes/kubelet

KUBELET_ADDRESS="--address=0.0.0.0"
KUBELET_PORT="--port=10250"
# change the hostname to this host’s IP address
KUBELET_HOSTNAME="--hostname_override=Minion1"
KUBELET_API_SERVER="--api_servers=http://Master:8080"
KUBELET_ARGS="--cluster-dns=10.254.3.100 --cluster-domain=cluster.local"

Configuramos Config en Minion1 – Solamente Modificamos la Linea KUBE_MASTER


vi /etc/kubernetes/config

KUBE_MASTER="--master=http://Master:8080"

REINICIAMOS SERVICIOS EN MINION1

for SERVICES in kube-proxy kubelet docker flanneld; do
systemctl restart $SERVICES
systemctl enable $SERVICES
systemctl status $SERVICES
done


Instalando Minion2 en Kubernetes:


setenforce 0
systemctl stop firewalld
systemctl disable firewalld
yum -y install ntp
systemctl start ntpd
systemctl enable ntpd
yum update -y
echo "172.16.0.1 Master
172.16.0.2 Minion1
172.16.0.3 Minion2
172.16.0.50 storage-nfs" >> /etc/hosts
yum -y install kubernetes flannel

Configuramos la red Flannel en el Minion2


vi /etc/sysconfig/flanneld

# etcd URL location. Point this to the server where etcd runs
FLANNEL_ETCD="http://172.16.0.1:2379"
# etcd config key. This is the configuration key that flannel queries
# For address range assignment
FLANNEL_ETCD_PREFIX="/kube-centos/network"
# Any additional options that you want to pass
FLANNEL_OPTIONS=""


Configuramos servicio de Kubelet en el Minion2


vi /etc/kubernetes/kubelet

KUBELET_ADDRESS="--address=0.0.0.0"
KUBELET_PORT="--port=10250"
# change the hostname to this host’s IP address
KUBELET_HOSTNAME="--hostname_override=Minion2"
KUBELET_API_SERVER="--api_servers=http://Master:8080"
KUBELET_ARGS="--cluster-dns=10.254.3.100 --cluster-domain=cluster.local"

Configuramos Config en Minion2 – Solamente Modificamos la Linea KUBE_MASTER


vi /etc/kubernetes/config

KUBE_MASTER="--master=http://Master:8080"

REINICIAMOS SERVICIOS EN MINION2

for SERVICES in kube-proxy kubelet docker flanneld; do
systemctl restart $SERVICES
systemctl enable $SERVICES
systemctl status $SERVICES
done


Si seguimos los pasos correctamente deberiamos ver en el Master los nodos correctamente y ya tendriamos nuestro Cluster de Kubernetes Configurado

[[email protected]]# kubectl get nodes
NAME STATUS AGE
172.16.0.2 Ready 2d
172.16.0.3 Ready 2d

6- Configurando Kubedns y Kubedashboard.


Kubedns: Instalando el servicio de DNS el cual nos permite resolver nuestro servicios por nombre FQDN.


Creamos el Archivo de Replicatión Controller


vi skydns-rc.yaml

apiVersion: v1
kind: ReplicationController
metadata:
  name: kube-dns-v20
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    version: v20
    kubernetes.io/cluster-service: "true"
spec:
  replicas: 1
  selector:
    k8s-app: kube-dns
    version: v20
  template:
    metadata:
      labels:
        k8s-app: kube-dns
        version: v20
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ''
        scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]'
    spec:
      containers:
      - name: kubedns
        image: gcr.io/google_containers/kubedns-amd64:1.8
        resources:
          # TODO: Set memory limits when we've profiled the container for large
          # clusters, then set request = limit to keep this container in
          # guaranteed class. Currently, this container falls into the
          # "burstable" category so the kubelet doesn't backoff from restarting it.
          limits:
            memory: 170Mi
          requests:
            cpu: 100m
            memory: 70Mi
        livenessProbe:
          httpGet:
            path: /healthz-kubedns
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
 failureThreshold: 5
        readinessProbe:
          httpGet:
            path: /readiness
            port: 8081
            scheme: HTTP
          # we poll on pod startup for the Kubernetes master service and
          # only setup the /readiness HTTP server once that's available.
          initialDelaySeconds: 3
          timeoutSeconds: 5
        args:
        # command = "/kube-dns"
        - --domain=cluster.local.
        - --dns-port=10053
        ports:
        - containerPort: 10053
          name: dns-local
          protocol: UDP
        - containerPort: 10053
          name: dns-tcp-local
          protocol: TCP
      - name: dnsmasq
        image: gcr.io/google_containers/kube-dnsmasq-amd64:1.4
        livenessProbe:
          httpGet:
            path: /healthz-dnsmasq
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        args:
        - --cache-size=1000
        - --no-resolv
        - --server=127.0.0.1#10053
        - --log-facility=-
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
      - name: healthz
        image: gcr.io/google_containers/exechealthz-amd64:1.2
        resources:
          limits:
            memory: 50Mi
          requests:
            cpu: 10m
            # Note that this container shouldn't really need 50Mi of memory. The
            # limits are set higher than expected pending investigation on #29688.
            # The extra memory was stolen from the kubedns container to keep the
            # net memory requested by the pod constant.
            memory: 50Mi
        args:
        - --cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1 >/dev/null
        - --url=/healthz-dnsmasq
        - --cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1:10053 >/dev/null
        - --url=/healthz-kubedns
        - --port=8080
        - --quiet
        ports:
        - containerPort: 8080
          protocol: TCP
      dnsPolicy: Default  # Don't use cluster DNS.

Creamos el Archivo de Servicio del DNS – SE DEBE CONFIGURAR LA IP DEL DNS QUE QUEREMOS CREAR EN MI CASO ES 10.254.3.100


vi skydns-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "KubeDNS"
spec:
  selector:
    k8s-app: kube-dns
  clusterIP: 10.254.3.100
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP

Procedemos a ejecutar nuestros archivos de configuración por 1ra vez


kubectl create -f skydns-rc.yaml
kubectl create -f skydns-svc.yaml

Revisamos que se creo todo correctamente revisamos el servicio y los pods corriendo.

[[email protected] servicios]# kubectl get svc -n kube-system
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns 10.254.3.100 <none> 53/UDP,53/TCP 2d

[[email protected] servicios]# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
kube-dns-v20-lxdfx 3/3 Running 9 2d

Probando el Servicio de DNS para ello vamos a generar una maquina muy liviana llamada busybox

[[email protected] pods]# vi busybox.yaml
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - image: busybox
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
    name: busybox
  restartPolicy: Always
[[email protected] pods]# kubectl create -f busybox.yaml
pod "busybox" created
[[email protected] pods]# kubectl get pods
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 47 1d

Teniendo la maquina de Busybox creada ejecutamos un nslookup de forma interactica en el pod y nos fijamos si resuelve el servicio kubernetes

[[email protected] pods]# kubectl exec -it busybox nslookup kubernetes
Server: 10.254.3.100
Address 1: 10.254.3.100 kube-dns.kube-system.svc.cluster.local

Name: kubernetes
Address 1: 10.254.0.1 kubernetes.default.svc.cluster.local

EJEMPLO: Tengo un microservicio creado llamado mariadb01 y vemos como se puede resolver por FQDN.


[[email protected] pods]# kubectl exec -it busybox nslookup mariadb01
Server: 10.254.3.100
Address 1: 10.254.3.100 kube-dns.kube-system.svc.cluster.local

Name: mariadb01
Address 1: 10.254.1.20 mariadb01.default.svc.cluster.local

KUBEDASHBOARD: Instalando el Dashboard Oficial de Kubernetes – En API debemos poner el Nodo donde queremos levantar el dashboard.


EJEMPLO: – –apiserver-host=http://172.16.0.1:8080


vi kubernetes-dashboard.yaml


kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  labels:
    app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kubernetes-dashboard
  template:
    metadata:
      labels:
        app: kubernetes-dashboard
      # Comment the following annotaion if Dashboard must not be deployed on master
      annotations:
        scheduler.alpha.kubernetes.io/tolerations: |
          [
            {
              "key": "dedicated",
              "operator": "Equal",
              "value": "master",
              "effect": "NoSchedule"
            }
          ]
    spec:
      containers:
      - name: kubernetes-dashboard
        image: gcr.io/google_containers/kubernetes-dashboard-amd64:v1.6.0
        imagePullPolicy: Always
        ports:
        - containerPort: 9090
          protocol: TCP
        args:
          # Uncomment the following line to manually specify Kubernetes API server Host
          # If not specified, Dashboard will attempt to auto discover the API server and connect
          # to it. Uncomment only if the default does not work.
          # - --apiserver-host=http://my-address:port
          - --apiserver-host=http://172.16.0.1:8080
        livenessProbe:
          httpGet:
            path: /
            port: 9090
          initialDelaySeconds: 30
          timeoutSeconds: 30
---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 9090
  selector:
    app: kubernetes-dashboard

Revisamos que nuestro Dashboard levanto correctamente: Ingresando por el navegador a 172.16.0.1:8080/ui



7- Configurando Monitoreo con Grafanna/Heapterz/InFluxdb.


Configurando Monitoreo con Grafanna y Influxdb: Lo primero que vamos hacer es clonar el repo de git y ingresar al directorio heapster/deploy/kube-config/influxdb ,una vez dentro del directorio ejecutamos kubectl create -f . y automaticamente se van a levantar todos los archivos yaml del directorio.

# git clone https://github.com/kubernetes/heapster.git
# cd heapster/deploy/kube-config/influxdb
# kubectl create -f .

Finalizada la creación de los pods y servicios, revisamos que esten corriendo bien


Si vemos una imagen como esta esta todo correcto entonces ingresamos en nuestro navegador a http://172.16.0.3:30616/ depende en que nodo esta corriendo el pod de grafana


WOW ! http://172.16.0.3:30616/ ya tenemos nuestro sistema de monitoreo de performance y adicionalmente kubedashboard se sirve de esta información GENIAL!!!


8- Instalando Storage-NFS Centos 7 y Configuración de almacenamiento persistente.


En un Servidor Centos 7 Instalamos el STORAGE-NFS


setenforce 0
systemctl stop firewalld
systemctl disable firewalld
yum -y install ntp
systemctl start ntpd
systemctl enable ntpd
yum update -y
echo "172.16.0.1 Master
172.16.0.2 Minion1
172.16.0.3 Minion2
172.16.0.50 storage-nfs" >> /etc/hosts
yum install nfs-utils
mkdir -p /shared/kubernetes/itshellweb/wordpress
mkdir -p /shared/kubernetes/itshellweb/mysql

**EDITAMOS LA CONFIGURACIÓN PARA COMPARTIR UN DIRECTORIO NFS**

vi /etc/exports

/shared 172.16.0.0/24(rw,sync,no_root_squash,no_all_squash)
systemctl enable rpcbind
systemctl enable nfs-server
systemctl restart rpcbind
systemctl restart nfs-server

EN TODOS LOS SERVIDORES DE NUESTRO CLUSTER | MINIONS Y MASTER


yum install nfs-utils -y
systemctl enable rpcbind
systemctl enable nfs-server
systemctl restart rpcbind
systemctl restart nfs-server
showmount -e storage-nfs

EJEMPLO: Si todo salio bien deberiamos ver algo asi.

[[email protected] zz]# showmount -e storage-nfs
Export list for storage-nfs:
/shared 172.16.0.0/24


9- Deploy Aplicación en Kubernetes.

Luego de seguir correctamente los pasos y tener nuestro Cluster en funcionamiento es hora de levantar una aplicación.
En mi caso voy a utilizar de ejemplo mi sitio, el mismo esta compuesto por una base de datos MYSQL y WORDPRESS.


Copiando los directorios de nuestra app de la DB y WWW.

a- Primero vamos a copiar nuestra base de datos a /shared/kubernetes/itshellweb/mysql
Luego vamos a otorgar permisos de escritura/lectura chmod 755 /shared/kubernetes/itshellweb/mysql
b- Vamos a realizar el mismo paso con los archivos de WordPress/WWW, copiamos los archivos de nuestro sitio
en /shared/kubernetes/itshellweb/wordpress
Ahora vamos a otorgar permisos de escritura/lectura chmod 755 /shared/kubernetes/itshellweb/


Finalizada la copia de los directorios vamos a proceder a crear nuestros volumenes de almacenamiento persistente.


[[email protected] storage]# vi mariadb1.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
    name: mariadb1-itshell
spec:
    capacity:
      storage: 2Gi
    accessModes:
      - ReadWriteMany
    persistentVolumeReclaimPolicy: Retain
    nfs:
     path: /shared/kubernetes/itshellweb/mysql
     server: storage-nfs

En este paso estamos indicando que tenemos un volumen de almacenamiento persistente que tiene 2GB, alojado en un storage nfs, Luego de realizar este paso debemos reclamar espacio de este volumen para poder montarlo en nuestra imagen a continuación podran ver en mi caso como realizarlo.


[[email protected] storage]# vi claim-mariadb1.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: claim-mariadb1-itshell
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 2Gi

Ahora ejecutamos los yaml de almacenamiento MYSQL.

[[email protected] storage]# kubectl create -f mariadb1.yaml
[[email protected] storage]# kubectl create -f claim-mariadb1.yaml

Revisamos que nuestro almacenamiento levanto correctamente


[[email protected] storage]# kubectl get pv,pvc
NAME                  CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS    CLAIM                            REASON    AGE
pv/mariadb1-itshell   2Gi        RWX           Retain          Bound     default/claim-mariadb1-itshell             1seg

NAME                         STATUS    VOLUME             CAPACITY   ACCESSMODES   AGE
pvc/claim-mariadb1-itshell   Bound     mariadb1-itshell   2Gi        RWX           10seg

Creando almacenamiento persistente de WWW y lo Reclamamos.


[[email protected] storage]# vi itshell-var.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
    name: itshell-var
spec:
    capacity:
      storage: 2Gi
    accessModes:
      - ReadWriteMany
    persistentVolumeReclaimPolicy: Retain
    nfs:
     path: /shared/kubernetes/itshellweb/wordpress
     server: storage-nfs

Reclamos el espacio de nuestro volumen creado.


[[email protected] storage]# vi claim-var.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: claim-var-itshell
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 2Gi

Ahora ejecutamos los yaml de almacenamiento WWW.

[[email protected] storage]# kubectl create -f itshell-var.yaml
[[email protected] storage]# kubectl create -f claim-var.yaml

Revisamos que nuestros almacenamientos levantaron correctamente.


[[email protected] storage]# kubectl get pv,pvc
NAME                  CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS    CLAIM                            REASON    AGE
pv/mariadb1-itshell   2Gi        RWX           Retain          Bound     default/claim-mariadb1-itshell             1seg
pv/itshell-var        2Gi        RWX           Retain          Bound     default/claim-var-itshell                  15seg
NAME                         STATUS    VOLUME             CAPACITY   ACCESSMODES   AGE
pvc/claim-mariadb1-itshell   Bound     mariadb1-itshell   2Gi        RWX           10seg
pvc/claim-var-itshell        Bound     itshell-var        2Gi        RWX           30seg

Replication Controller para MYSQL/MARIADB: En este caso voy a crear solamente una replica de MYSQL ya que si queremos mas deberiamos armar un cluster.

Antes de continuar quiero hacer una aclaración nosotros llamamos los volumenes generados por el nombre de la variable claim que creamos por ejemplo estamos llamando a claim-mariadb1-itshell.


vi mariadb01-rc.yaml

apiVersion: v1
kind: ReplicationController
metadata:
  name: mariadb01-it
  labels:
    name: mariadb01-it
spec:
  replicas: 1
  selector:
    name: mariadb01-it
  template:
    metadata:
      labels:
        name: mariadb01-it
    spec:
      containers:
      - name: mariadb01-it
        image: mysql:5.6
        ports:
        - containerPort: 3306
          name: mariadb01-it
        env:
          - name: MYSQL_ROOT_PASSWORD
            value: "root"
          - name: MYSQL_DATABASE
            value: itshelldb
          - name: MYSQL_ROOT_PASSWORD
            value: root
          - name: MYSQL_USER
            value: root
        volumeMounts:
          - name: claim-mariadb1-itshell
            mountPath: /var/lib/mysql
      volumes:
        - name: claim-mariadb1-itshell
          persistentVolumeClaim:
           claimName: claim-mariadb1-itshell
kubectl create -f mariadb01-rc.yaml

Microservicio de MARIADB/MYSQL – Lo vamos a llamar mariadb01-it.

[[email protected] mariadb01]# vi mariadb01-svc.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    name: mariadb01-it
  name: mariadb01-it
spec:
  clusterIP: 10.254.1.70
  ports:
    - port: 3306
  selector:
    name: mariadb01-it
kubectl create -f mariadb01-svc.yaml

y nuevamente revisamos que levanto correctamente…


[[email protected] mariadb01]# kubectl get svc
NAME           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes     10.254.0.1       <none>        443/TCP        15d
mariadb01-it   10.254.1.70      <none>        3306/TCP       1h

Replication Controller de WORDPRESS: Ya vimos como levantar un microservicio de mysql ahora vamos a levantar el de wordpress.

NOTA: Cuando llamo al volumen por el claim siempre se debe respetar el nombre de la variable, pero el nombre de configuraciòn de volumen lo podemos cambiar como se representa en este otro yaml.

En este caso voy a levantar 3 replicas de WordPress que van a terminar en diferentes servidores y vamos a publicar el servicio el cual va a tener los ENDPOINTS balanceados.

[[email protected] apache]# vi itshell-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: itshell
  labels:
    name: itshell
spec:
  replicas: 3
  selector:
    name: itshell
  template:
    metadata:
      labels:
        name: itshell
    spec:
      containers:
      - name: itshell
        image: wordpress
        ports:
        - containerPort: 80
          name: itshell
        env:
          - name: WORDPRESS_DB_USER
            value: root
          - name: WORDPRESS_DB_PASSWORD
            value: root
          - name: WORDPRESS_DB_NAME
            value: itshelldb
          - name: WORDPRESS_DB_HOST
            value: mariadb01-it
        volumeMounts:
          - name: wordpress-1
            mountPath: /var/www/html
      volumes:
        - name: wordpress-1
          persistentVolumeClaim:
           claimName: claim-var-itshell
kubectl create -f itshell-rc.yaml

Publicando nuestro servicio en mi ip privada esto se podria realizar tmb con una IP publica, tambien se puede publicar en varias ips.


vi Load-balancer-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: itshell
spec:
  externalIPs:
  - 172.16.0.3
  ports:
  - name: http
    port: 80
    targetPort: 80
  selector:
    name: itshell
  type: LoadBalancer
kubectl create -f Load-balancer-svc.yaml
kubectl get svc
NAME           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
itshell        10.254.230.89    ,172.16.0.3   80:31443/TCP   1h
mariadb01-it   10.254.1.70      <none>        3306/TCP       1h


NOTA: En este caso utilize la publicaciòn como Loadbalancer que puede ser en varios nodos pero tambien podemos utilizar el tipo NodePort el cual publica en un Nodo especifico y puerto especifico.


Vamos a comprobar que todo salio con exito y vemos si nuestro sitio levanto correctamente.(Depende como tengamos nuestra base de datos mysql a veces debemos dar acceso a la red flannel de Kubernetes para que los servidores se puedan conectar)


Los comandos para realizar troobleshooting son:
kubectl describe po “ID del contenedor” – Lo utilizamos en caso de un contenedor que no se creo correctamente.
kubectl logs “ID del contenedor” – Lo utilizamos en un contenedor creado correctamente y vemos el Log.


Nuestro Sitio Funcionando en Kubernetes!



Podemos levantar Aplicaciones mas complejas que corran redis,mongodb,memcache,etc


EJEMPLO:


Estado de nuestro Cluster con varias aplicaciones:


Les enviò un saludo a todos y gracias por su tiempo.

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *