Kubernetes en GCE
Creación de un laboratorio Kubernetes en GCE
(Siguiendo la guía de Kelsey Hightower - Kubernetes up and running)
Importar la imagen que usaremos en los nodos de trabajo (contenedores docker)
gcloud compute images create kubernetes-1-0-6-v20151004 --source-uri https://storage.googleapis.com/kuar/kubernetes-1-0-6-v20151004.tar.gz
Generar los nodos (4 nodos)
gcloud compute instances create nodo1 --image kubernetes-1-0-6-v20151004 --boot-disk-size 200GB --machine-type n1-standard-1 --can-ip-forward --scopes compute-rw --zone europe-west1-b
Configuración del Docker Engine
Tengo problemas con la imagen y tengo que instalar el paquete docker.io. Después modifico el fichero de arranque del servicio.[Unit]
Description=Docker Application Container Engine
Documentation=http://docs.docker.com
After=network.target docker.socket
Requires=docker.socket
[Service]
EnvironmentFile=-/etc/default/docker
ExecStart=/usr/local/bin/docker --daemon
--bip=10.10.10.1/24
--iptables=false
--ip-masq=false
--host=unix:///var/run/docker.sock
--storage-driver=overlay
Restart=on-failure
RestartSec=5
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
[Install]
WantedBy=multi-user.target
Los argumentos que se le pasan al engine hacen que la red de los contenedores sea la especificada como --bip, se desactiva el iptables y el ip-masq de modo que el engine no hace Nat sobre los paquetes de red que salen del nodo. Los paquetes saldrán con la IP especificado en --bip
Configuramos los tres nodos de la misma manera.
Ahora tenemos que indicarle a nuestras instancias como "hablar" entra ellas, para ello definimos rutas a nivel de nuestro proyecto. Definimos 4 rutas como la que se muestra a continuación.
Para terminar, necesitamos que nuestros nodos enmascaren el tráfico que no fluye hacia la red de contenedores y entre los contenedores. Le hemos indicado a nuestro docker engine que no enmascare el tráfico y por lo tanto tenemos que hacer nosotros. En cada nodo:
En este punto nuestros contenedores deben tener salida a Internet y podrán "hablar" entre ellos por la red IP establecida en los contenedores.
[Service]
ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifest
ExecStart=/usr/local/bin/kubelet
--api-servers=http://nodo0:8080
--allow-privileged=true
--cluster-dns=10.10.100.10
--cluster-domain=cluster.local
--config=/etc/kubernetes/manifest
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
- "--listen-client-urls=http://127.0.0.1:2379"
- "--listen-peer-urls=http://127.0.0.1:2380"
- "--name=etcd"
volumeMounts:
- mountPath: /var/lib/etcd
name: "etcd-datadir"
Necesitamos otro pod para el apiserver. Creamos el fichero kube-apiserver-pod.yaml en la misma carpeta anterior con este contenido:
kind: Pod
metadata:
name: kube-controller-manager
spec:
hostNetwork: true
containers:
- name: "kube-controller-manager"
image: "b.gcr.io/kuar/kube-controller-manager:1.0.6"
args:
- "--master=http://127.0.0.1:8080"
kind: Pod
metadata:
name: kube-scheduler
spec:
hostNetwork: true
containers:
- name: "kube-scheduler"
image: "b.gcr.io/kuar/kube-scheduler:1.0.6"
args:
- "--master=http://127.0.0.1:8080"
{
"kind": "ComponentStatus",
"apiVersion": "v1",
"metadata": {
"name": "controller-manager",
"selfLink": "/api/v1/namespaces/componentstatuses/controller-manager",
"creationTimestamp": null
},
"conditions": [
{
"type": "Healthy",
"status": "True",
"message": "ok",
"error": "nil"
} ]
curl http://127.0.0.1:8080/api/v1/namespaces/default/componetstatuses/scheduler
{
"kind": "ComponentStatus",
"apiVersion": "v1",
"metadata": {
"name": "scheduler",
"selfLink": "/api/v1/namespaces/componentstatuses/scheduler",
"creationTimestamp": null
},
"conditions": [
{
"type": "Healthy",
"status": "True",
"message": "ok",
"error": "nil"
} ]
Configuramos los tres nodos de la misma manera.
Nodo | IP | Nombre interno | Nombre externo |
nodo0 | 10.10.0.1/24 | nodo0.c.grand-loop-111013.internal | extern0 |
nodo1 | 10.10.10.1/24 | nodo1.c.grand-loop-111013.internal | extern1 |
nodo2 | 10.10.20.1/24 | nodo2.c.grand-loop-111013.internal | extern2 |
nodo2 | 10.10.30.1/24 | nodo3.c.grand-loop-111013.internal | extern3 |
Ahora tenemos que indicarle a nuestras instancias como "hablar" entra ellas, para ello definimos rutas a nivel de nuestro proyecto. Definimos 4 rutas como la que se muestra a continuación.
gcloud compute routes create default-route-10-10-10-0-24 --destination-range 10.10.10.0/24 --next-hop-instance nodo1 --next-hop-instance-zone europe-west1-b
En este punto, las máquinas deben de tener comunicación entre las diferentes redes docker.Para terminar, necesitamos que nuestros nodos enmascaren el tráfico que no fluye hacia la red de contenedores y entre los contenedores. Le hemos indicado a nuestro docker engine que no enmascare el tráfico y por lo tanto tenemos que hacer nosotros. En cada nodo:
sudo iptables -t nat -A POSTROUTING ! -d 10.0.0.0/8 -o eth0 -j MASQUERADE
sudo iptables-save
En este punto nuestros contenedores deben tener salida a Internet y podrán "hablar" entre ellos por la red IP establecida en los contenedores.
Generamos el servicio Kubelet
Este servicio se encarga de manejar los pods (agrupación de contenedores similares que comparten volúmenes y red), los puntos de montaje, el registro de los nodos y de reportar las métricas y el estado de los servicios al servidor API.[Unit]
Description=Kubelet
Documentation=http://kubernetes.com
After=docker.service
Requires=docker.servic
e[Service]
ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifest
ExecStart=/usr/local/bin/kubelet
--api-servers=http://nodo0:8080
--allow-privileged=true
--cluster-dns=10.10.100.10
--cluster-domain=cluster.local
--config=/etc/kubernetes/manifest
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Kubernetes Controller node
El controller node lo montamos en el nodo0 creando el fichero etcd-pod.yaml en /etc/kubernetes/manifests/.apiVersion: v1
kind: Pod
metadata:
name: etcd
spec:
hostNetwork: true
volumes:
- name: "etcd-datadir"
hostPath:
path: "/var/lib/etcd"
containers:
- name: "etcd"
image: "b.gcr.io/kuar/etcd:2.2.0"
args:
- "--data-dir=/var/lib/etcd"
- "--advertise-client
-urls=http://127.0.0.1:2379"- "--listen-client-urls=http://127.0.0.1:2379"
- "--listen-peer-urls=http://127.0.0.1:2380"
- "--name=etcd"
volumeMounts:
- mountPath: /var/lib/etcd
name: "etcd-datadir"
Necesitamos otro pod para el apiserver. Creamos el fichero kube-apiserver-pod.yaml en la misma carpeta anterior con este contenido:
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
spec:
hostNetwork: true
containers:
- name: "kube-apiserver"
image: "b.gcr.io/kuar/kube-apiserver:1.0.6"
args:
- "--allow-privileged=true"
- "--etcd-servers=http://127.0.0.1:2379"
- "--insecure-bind-address=0.0.0.0"
- "--service-cluster-ip-range=10.200.100.0/24"
- "--service-node-port-range=30000-37000"
Kube Controller manager
apiVersion: v1kind: Pod
metadata:
name: kube-controller-manager
spec:
hostNetwork: true
containers:
- name: "kube-controller-manager"
image: "b.gcr.io/kuar/kube-controller-manager:1.0.6"
args:
- "--master=http://127.0.0.1:8080"
Kube scheduler
apiVersion: v1kind: Pod
metadata:
name: kube-scheduler
spec:
hostNetwork: true
containers:
- name: "kube-scheduler"
image: "b.gcr.io/kuar/kube-scheduler:1.0.6"
args:
- "--master=http://127.0.0.1:8080"
Verificamos los componentes
curl http://127.0.0.1:8080/api/v1/namespaces/default/componentstatuses/controller-manager{
"kind": "ComponentStatus",
"apiVersion": "v1",
"metadata": {
"name": "controller-manager",
"selfLink": "/api/v1/namespaces/componentstatuses/controller-manager",
"creationTimestamp": null
},
"conditions": [
{
"type": "Healthy",
"status": "True",
"message": "ok",
"error": "nil"
} ]
curl http://127.0.0.1:8080/api/v1/namespaces/default/componetstatuses/scheduler
{
"kind": "ComponentStatus",
"apiVersion": "v1",
"metadata": {
"name": "scheduler",
"selfLink": "/api/v1/namespaces/componentstatuses/scheduler",
"creationTimestamp": null
},
"conditions": [
{
"type": "Healthy",
"status": "True",
"message": "ok",
"error": "nil"
} ]
Verificamos el sistema
xxxxx@nodo0:/etc/kubernetes/manifest$ kubectl get nodes
NAME LABELS STATUS
nodo0 kubernetes.io/hostname=nodo0 Ready
nodo1 kubernetes.io/hostname=nodo1 Ready
nodo2 kubernetes.io/hostname=nodo2 Ready
nodo3 kubernetes.io/hostname=nodo3 Ready
xxxxx@nodo0:/etc/kubernetes/manifest$ kubectl get pods
NAME READY STATUS RESTARTS AGE
etcd-nodo0 1/1 Running 0 3m
kube-apiserver-nodo0 1/1 Running 2 3m
kube-controller-manager-nodo0 1/1 Running 0 3m
kube-proxy-nodo0 1/1 Running 0 3m
kube-proxy-nodo1 1/1 Running 0 3m
kube-proxy-nodo2 1/1 Running 0 2m
kube-proxy-nodo3 1/1 Running 0 52s
kube-scheduler-nodo0 1/1 Running 0 3m
xxxxxx@nodo0:/etc/kubernetes/manifest$ kubectl get componentstatuses
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok nil
scheduler Healthy ok nil
etcd-0 Healthy {"health": "true"} nil
Arrancar la UI de Kubernetes
A partir de dos ficheros yaml generamos la interfaz gráfica:Kube-ui-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: kube-ui-v1
namespace: kube-system
labels:
k8s-app: kube-ui
version: v1
kubernetes.io/cluster-service: "true"
spec:
replicas: 1
selector:
k8s-app: kube-ui
version: v1
template:
metadata:
labels:
k8s-app: kube-ui
version: v1
kubernetes.io/cluster-service: "true"
spec:
containers:
- name: kube-ui
image: gcr.io/google_containers/kube-ui:v1.1
resources:
limits:
cpu: 100m
memory: 50Mi
ports:
- containerPort: 8080
Kube-ui-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: kube-ui
namespace: kube-system
labels:
k8s-app: kube-ui
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "KubeUI"
spec:
selector:
k8s-app: kube-ui
ports:
- port: 80
targetPort: 8080
Ahora cargamos los ficheros:
kubectl create -f kube-ui-rc.yaml --namespace=kube-system
kubectl create -f kube-ui-svc.yaml --namespace=kube-system
En nuestro cluster, el nodo0 tiene desplegada la UI de Kubernetes en el puerto 8080.
Comentarios
Publicar un comentario