viernes, 18 de marzo de 2016

Configurando kubectl para usar GCE o lo que se te ocurra....


  1. Instalar los componentes de gcloud ()
  2. Instalar el componente kubectl (gcloud components update kubectl)
  3. Configurar el proyecto por defecto (gcloud config set project xxxxxx-XXXXX)
  4. Configurar la zona (gcloud config set compute/zone europe-west1-d)
  5. Configurar el nombre del cluster (gcloud config set container/cluster  mi-cluster)
  6. Obtener los datos de acceso (gcloud container clusters get-credentials mi-cluster)
  Ya podemos mandar comandos al cluster k8s:

  1. kubectl get nodes
  2. NAME                                          LABELS                                                               STATUS    AGE
    gke-k8s-pre-opencanarias-8d8c059c-node-petk   kubernetes.io/hostname=gke-k8s-pre-opencanarias-8d8c059c-node-petk   Ready     40m
    gke-k8s-pre-opencanarias-8d8c059c-node-rurs   kubernetes.io/hostname=gke-k8s-pre-opencanarias-8d8c059c-node-rurs   Ready     40m

  3. kubectl cluster-info 
  4. Kubernetes master is running at https://104.155.39.104 GLBCDefaultBackend is running at https://104.155.39.104/api/v1/proxy/namespaces/kube-system/services/default-http-backend Heapster is running at https://104.155.39.104/api/v1/proxy/namespaces/kube-system/services/heapster KubeDNS is running at https://104.155.39.104/api/v1/proxy/namespaces/kube-system/services/kube-dns KubeUI is running at https://104.155.39.104/api/v1/proxy/namespaces/kube-system/services/kube-ui

... ya lo puedes probar...

miércoles, 11 de noviembre de 2015

Kubernetes en GCE

Creación de un laboratorio Kubernetes en GCE

(Siguiendo la guía de Kelsey Hightower - Kubernetes up and running)

Vamos a generar un laboratorio para usar Kubernetes como entorno de producción en la nube de Google GCE. Partimos del punto en que tenemos nuestro usuario con acceso al GCE donde podemos empezar a generar servidores para montar el cluster Kubernetes.

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.

NodoIPNombre internoNombre externo
nodo010.10.0.1/24nodo0.c.grand-loop-111013.internalextern0
nodo110.10.10.1/24nodo1.c.grand-loop-111013.internalextern1
nodo210.10.20.1/24nodo2.c.grand-loop-111013.internalextern2
nodo210.10.30.1/24nodo3.c.grand-loop-111013.internalextern3

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.service

[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: v1
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"

Kube scheduler

apiVersion: v1
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"

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.


miércoles, 28 de octubre de 2015

GCE (Google Compute Engine)

Mis primeros pasos

Estamos evaluando nuevos mercados en la empresa y esto me ha llevado a valorar los servicios de Google Compute Engine. A modo de documentación voy a poner los comandos que voy necesitando en esta andadura.

Antes de acceder a la consola debemos registrarnos con nuestra cuenta de gmail.

Instalación

curl https://sdk.cloud.google.com | bash
exec -l $SHELL
gcloud init

Definir una zona por defecto

gcloud compute project-info add-metadata --metadata google-compute-default-region=europe-west1, google-compute-default-zone=europe-west1-b
gcloud config set compute/zone europe-west1-b
gcloud config list
[compute]
zone = europe-west1-b
[core]
account = XXXXXXX-compute@developer.gserviceaccount.com
project = grand-loop-XXXXX 

Ayuda

gcloud --help
gcloud compute --help
gcloud compute instances list

Información

gcloud compute project-info describe

Actualización de los componentes

gcloud components update

Conexión por SSH contra nuestras instancias

gcloud compute ssh test01 --zone europe-west1-b

También podemos usar nuestro propio cliente ssh

gcloud compute config-ssh
ssh test01.europe-west1-b.grand-loop-XXXXX

Subir imágenes al registro privado del proyecto

docker tag myuser/busyboxtest eu.gcr.io/grand-loop-XXXXX/busyboxtest
gcloud docker push eu.gcr.io/grand-loop-XXXXXX/busyboxtest




viernes, 5 de septiembre de 2014

Instalando CoreOS sobre KVM

Como hago siempre, para instalar un sistema operativo suelo buscar una imagen ISO para cargarla en el Hipervisor. En este caso bajé la imagen que está disponible en la web de CoreOs. Generé una máquina virtual nueva, 8 Gb de disco duro, 1024 Mb de memoria y 1 CPU. Arranco desde la ISO y me lleva a esta pantalla:

 

En la web de CoreOs se nos indica que esta imagen no es un S.O. y que hay que realizar una serie de tareas para poder desplegar el nuevo servidor.

  1. Desde el prompt ejecuto el comando sudo su
  2. Ahora ejecuto coreos-install -d /dev/sda

 Ahora el sistema nuevo arranca...pero no hay manera de acceder. La documentación de CoreOS nos indica que debemos crear un fichero "cloud-config" de configuración que será ejecutado con cada arranque del S.O. o si se invoca el comando "coreos-cloudinit".

sábado, 16 de noviembre de 2013

Todo los días se aprende algo nuevo...

Cuando se genera un nuevo sistema de ficheros y lo montamos, vemos que en su interior existe una carpeta lost+found. Esta carpeta se utiliza cuando se pasa la utilidad e2fsck y aparecen bloques huerfanos. La carpeta se genera por medio del comando mklost+found, la cual, reserva bloques de datos para alojar los ficheros huerfanos.

...parece que nunca terminas de aprender cosas... ...el mundo sería aburrido si no tenemos cosas que aprender... 

sábado, 9 de noviembre de 2013

Construcción de un paquete rpm

Los paquetes de distribución de software que usan las distribuciones linux Red Hat y CentOS son en formato rpm. En debian y derivados, como ubuntu, los paquetes son en formato deb. Entre los objetivos a conocer para el RHCSA es necesario saber construir un paquete rpm.

Los paquetes rpm deben ser construidos en una estructura de directorios predeterminada:

BUILD

BUILDROOT

RPMS

SOURCES

SPECS

SRPMS

Esta estructura y para hacernos el trabajo más simple se puede generar con el comando rpmdev-setuptree, las estructura se genera en la carpeta incial del usuario bajo la carpeta rpmbuild.

Para construir un paquete rpm necesitamos un fichero, .spec, que le indique a la aplicación rpmbuild que construir y como. Al instalar el paquete rpmdevtools, en la carpeta /etc/rpmdevtools/ se nos dejan varios ficheros plantilla y en nuestro caso usaremos el fichero spectemplate-minimal.spec. También se puede hacer uso del comando rpmdev-newspec, el cual genera el mismo fichero con el nombre newpackage.spec. El fichero .spec debe estar colocado en la carpeta SPECS.

Para generar el paquete rpm necesitamos basarnos en un fichero .tar con el contenido de nuestro paquete. El fichero se debe colocar en la carpeta SOURCES. Para este ejemplo he generado una carpeta que contiene lo siguiente:

./vsconf-personal:

total 8

-rwxr-xr-x. 1 root root    0 nov  9 18:31 configure

drwxr-xr-x. 3 root root 4096 nov  3 20:15 etc

drwxr-xr-x. 3 root root 4096 nov  9 09:23 opt

./vsconf-personal/etc:

total 4

drwxr-xr-x. 2 root root 4096 nov  9 09:22 vsftpd

./vsconf-personal/etc/vsftpd:

total 8

-rw-------. 1 root root 4617 nov  3 20:06 mi_vsftpd.conf

./vsconf-personal/opt:

total 4

-rw-r--r--. 1 root root    0 nov  9 09:23 fileone

-rw-r--r--. 1 root root    0 nov  9 09:23 filetwo

drwxr-xr-x. 2 root root 4096 nov  9 09:23 uno

./vsconf-personal/opt/uno:

total 0

-rw-r--r--. 1 root root 0 nov  9 09:23 Oneeee

 

-rw-r--r--. 1 root root 0 nov  9 09:23 Twoooo

Atención al fichero configure (Se usa para configurar un fuente antes de compilarlo, en nuestro caso no lo usaremos), vacío y con permisos de ejecución. La idea es que el fichero mi_vsftpd.conf se coloque en la carpeta /etc/vsftpd. En la carpeta /opt se generan dos ficheros (fileone y filetwo). Además se crea la carpeta uno con los fichero Oneeee y Twoooo en su interior. De esta estructura generamos un fichero vsconf-personal.tar

Tras renombrar el fichero newpackage.spec como vsconf-personal.spec que inicialmente tiene la siguiente información:

Name:           

Version:        

Release:        1%{?dist}

Summary:        

 

Group:          

License:        

URL:            

Source0:        

 

BuildRequires:  

Requires:       

 

%description

 

 

%prep

%setup -q

 

 

%build

%configure

make %{?_smp_mflags}

 

 

%install

rm -rf $RPM_BUILD_ROOT

make install DESTDIR=$RPM_BUILD_ROOT

 

%clean

rm -rf $RPM_BUILD_ROOT

 

%files

%defattr(-,root,root,-)

%doc

 

 

%changelog

Editamos el fichero y lo dejamos de la siguiente manera:

Name:          vsconf-personal

Version:       1.0 

Release:        1%{?dist}

Summary:       This is a summary test 

License:       GPL

Source0:        vsconf-personal.tar

 

%description

Desc1

Desc2

Desc3

Desc4

 

%prep

#%setup -q

%setup -n vsconf-personal

 

 

#%build

#%configure

#make %{?_smp_mflags}

 

 

%install

rm -rf $RPM_BUILD_ROOT

#make install DESTDIR=$RPM_BUILD_ROOT

mkdir $RPM_BUILD_ROOT

cp -r * $RPM_BUILD_ROOT/

rm -f $RPM_BUILD_ROOT/configure

 

%clean

rm -rf $RPM_BUILD_ROOT

 

 

%files

%defattr(-,root,root,-)

%doc

#%dir /opt/uno

/etc/vsftpd/mi_vsftpd.conf

/opt/fileone

/opt/filetwo

/opt/uno/Oneeee

/opt/uno/Twoooo

 

 

%changelog

%setup -n vsconf-personal --> Con este cambio indicamos durante la construcción donde está el fichero .tar a usar.

Con las lineas mkdir $RPM_BUILD_ROOTcp -r * $RPM_BUILD_ROOT/ generamos una carpeta  y copiamos nuestros ficheros que luego se empaquetan en nuestro rpm. La linea rm -f $RPM_BUILD_ROOT/configure elimina el fichero configure del paquete.

%files --> Ponemos los ficheros que queremos que se copian al instalar el paquete rpm.

El paquete rpm se genera ejecutando el comando rpmbuild -bb vsconf-personal.spec. El resultado se deja en la carpeta rpmbuild/RPMS/x86_64/vsconf-personal-1.0-1.el6.x86_64.rpm . El parámetro -bb hace que se genere el instalador binario. 

 

viernes, 1 de noviembre de 2013

Restringir acceso vía SSH por usuario y grupos

Es impresionante lo que uno puede hacer vía ssh en un servidor Linux. En una de mis entradas del blog ya hablo de túneles ssh y túneles ssh inversos. Ahora, y con motivo del RHCSA he tenido que hacer un laboratorio donde se te pide que restrinjas el acceso a un servidor vía ssh a un usuario en concreto. En la documentación del demonio ssh aparece una entrada que se puede colocar en la configuración y de esta manera denegar el acceso a un usuario.

DenyUsers

Se trata de una lista de usuarios, separada por comas o espacios, del sistema destino con el host desde el que van realizar el acceso.

Un ejemplo:

DenyUsers user1@server1, user2@server1.example.org

DenyGroups

Es análogo al anterior pero usando grupos de usuarios del sistema destino.

Nota:

También existen las directivas AllowUsers y AllowGroups. Por defecto se permite acceso a todos los usuarios. Si cambiamos este compartamiento, esta directiva nos permite hacer una lista de usuarios con acceso al servidor.