Обновлено 21/08/2020. С момента написания статьи прошло чуть больше года и ряд примеров перестали работать — технологии развиваются, поэтому немного дополнил и переделал примеры.
В данной статье я хотел бы рассказать об установке Kubernetes на Hetzner Cloud.
На моем рабочем компьютере установлен Ubuntu Linux 18.04 и все примеры будут подразумевать использование данной операционной системы.
Для работы с Hetzner Cloud и построения кластера Kubernetes мы будем использовать утилиту hetzner-kube. Установим ее на свой локальный компьютер.
Для работы утилиты hetzner-kube и ее авторизации в Hetzner Cloud необходимо создать API Token через Hetzner Cloud Console https://console.hetzner.cloud. Вверху выбираем Select a project -> Default, в левом меню выбираем пункт Access, далее переходим в раздел API tokens, нажимаем на кнопку Generate API Token.
В результате будет сгенерирован API Token и его необходимо будет указать в конфигурации утилиты hetzner-kube.
Далее нам необходимо сгенерировать SSH ключ, который будет использоваться для доступа к серверам в Hetzner Cloud. Для этого воспользуемся утилитой ssh-keygen:
В результате в вашем домашнем каталоге будет создано два файла ~/.ssh/id_rsa (приватный ключ) и ~/.ssh/id_rsa.pub (публичный ключ).
Добавим публичный ssh ключ в Hetzner Cloud:
Непосредственно построение кластера Kubernetes выполняется очень легко:
Данная команда автоматически создаст виртуальные сервера в Hetzner Cloud и установит на них указанное количество master/worker нод кластера Kubernetes. По-умолчанию, будут использованы CX11 виртуальные сервера.
В дальнейшем, с помощью утилиты hetzner-kube, также легко изменить конфигурацию кластера Kubernetes добавляя worker ноды. Например, добавим 2 worker ноды:
К сожалению, изменить конфигурацию master нод с помощью утилиты hetzner-kube без полного пересоздания кластера Kubernetes на данный момент времени не представляется возможным.
Для работы с Kubernetes кластером используется утилита kubectl. Подробную инструкцию по ее установке для разных операционных систем можно найти по следующей ссылке.
Для того, чтобы работать с созданным кластером Kubernetes с помощью команды kubectl, необходимо сохранить локально конфигурацию созданного кластера следующим образом:
Файл с конфигурацией сохраняется в ~/.kube/config.
Теперь переходим к самому интересному — конфигурированию полученного кластера Kubernetes.
Для начала создадим базовые ресурсы необходимые для будущего развертывания приложений. Более подробную информацию вы сможете найти по следующей ссылке.
Далее необходимо, чтобы нам ingress контроллер был доступен из Интернета. Для этого с помощью утилиты kubectl редактируем service/ingress-nginx и добавляем в него список публичных IP адресов worker/master нод нашего Кубернетес кластера (только те, которые мы хотим использовать для обработки входящих запросов из Интернета).
и добавляем следующий раздел в YAML манифест
Добавляем А записи в ваш домен и ждем пока информация о них появится в ДНС. Например:
Если в ingress-nginx.yaml вы указали несколько внешних IP адресов, то можно создать несколько одинаковых DNS записей с этими IP адресами. В этом случае запросы на ваш домен будут распределяться между этими IP адресами и будет происходить балансировка нагрузки.
В данном примере для работы https сгенерируем самоподписанный SSL сертификат.
Теперь добавляем наше приложение. В качестве примера выбран простой echoserver. Создаем файл с именем app.yaml и следующим содержимым:
На этом все )) Проверяем результат:
В данной статье я хотел бы рассказать об установке Kubernetes на Hetzner Cloud.
На моем рабочем компьютере установлен Ubuntu Linux 18.04 и все примеры будут подразумевать использование данной операционной системы.
Для работы с Hetzner Cloud и построения кластера Kubernetes мы будем использовать утилиту hetzner-kube. Установим ее на свой локальный компьютер.
$ wget https://github.com/xetys/hetzner-kube/releases/download/0.5.1/hetzner-kube-0.5.1-linux-amd64
$ chmod a+x ./hetzner-kube-0.5.1-linux-amd64
$ sudo mv ./hetzner-kube-0.5.1-linux-amd64 /usr/local/bin/hetzner-kube
Для работы утилиты hetzner-kube и ее авторизации в Hetzner Cloud необходимо создать API Token через Hetzner Cloud Console https://console.hetzner.cloud. Вверху выбираем Select a project -> Default, в левом меню выбираем пункт Access, далее переходим в раздел API tokens, нажимаем на кнопку Generate API Token.
В результате будет сгенерирован API Token и его необходимо будет указать в конфигурации утилиты hetzner-kube.
$ hetzner-kube context add k8s
Token: <PASTE TOKEN HERE>
added context 'k8s'
Далее нам необходимо сгенерировать SSH ключ, который будет использоваться для доступа к серверам в Hetzner Cloud. Для этого воспользуемся утилитой ssh-keygen:
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (~/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ~/.ssh/id_rsa.
Your public key has been saved in ~/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:1bwptZ8lPiAhtA37/2U1G7HsC+aE7qMVCtVIfN3OLzk lx4241@LX4241-LINUX
The key's randomart image is:
+---[RSA 2048]----+
| +. . . |
| ..*o+ . . |
| +o=.+ o. |
| .+ o +.oo|
| .S +.= .*+|
| . .+o+E+*|
| . o.+==o|
| o.+..+.|
| .oo.... |
+----[SHA256]-----+
В результате в вашем домашнем каталоге будет создано два файла ~/.ssh/id_rsa (приватный ключ) и ~/.ssh/id_rsa.pub (публичный ключ).
Добавим публичный ssh ключ в Hetzner Cloud:
$ hetzner-kube ssh-key add --name k8s
sshKeyAdd called
SSH key k8s(95430) created
Непосредственно построение кластера Kubernetes выполняется очень легко:
$ hetzner-kube cluster create --name k8s --ssh-key k8s --master-count 1 --worker-count 1
2018/08/02 13:57:57 Creating new cluster
NAME:k8s
MASTERS: 1
WORKERS: 1
ETCD NODES: 0
HA: false
ISOLATED ETCD: false
2018/08/02 13:57:58 creating server 'k8s-master-01'...
--- [======================================] 100%
2018/08/02 13:58:18 Created node 'k8s-master-01' with IP 159.69.54.228
2018/08/02 13:58:18 creating server 'k8s-worker-01'...
--- [======================================] 100%
2018/08/02 13:58:37 Created node 'k8s-worker-01' with IP 159.69.51.140
2018/08/02 13:58:37 sleep for 10s...
k8s-master-01 : complete! 100.0% [==============]
k8s-worker-01 : complete! 100.0% [==============]
2018/08/02 14:02:50 Cluster successfully created!
Данная команда автоматически создаст виртуальные сервера в Hetzner Cloud и установит на них указанное количество master/worker нод кластера Kubernetes. По-умолчанию, будут использованы CX11 виртуальные сервера.
В дальнейшем, с помощью утилиты hetzner-kube, также легко изменить конфигурацию кластера Kubernetes добавляя worker ноды. Например, добавим 2 worker ноды:
$ hetzner-kube cluster add-worker --name k8s --nodes 2
К сожалению, изменить конфигурацию master нод с помощью утилиты hetzner-kube без полного пересоздания кластера Kubernetes на данный момент времени не представляется возможным.
Для работы с Kubernetes кластером используется утилита kubectl. Подробную инструкцию по ее установке для разных операционных систем можно найти по следующей ссылке.
Для того, чтобы работать с созданным кластером Kubernetes с помощью команды kubectl, необходимо сохранить локально конфигурацию созданного кластера следующим образом:
$ hetzner-kube cluster kubeconfig k8s
create file
kubeconfig configured
Файл с конфигурацией сохраняется в ~/.kube/config.
Теперь переходим к самому интересному — конфигурированию полученного кластера Kubernetes.
Для начала создадим базовые ресурсы необходимые для будущего развертывания приложений. Более подробную информацию вы сможете найти по следующей ссылке.
$ curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/baremetal/deploy.yaml | kubectl apply -f -
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 6170 100 6170 0 0 13987 0 --:--:-- --:--:-- --:--:-- 14022
namespace/ingress-nginx created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
deployment.apps/nginx-ingress-controller created
limitrange/ingress-nginx created
Далее необходимо, чтобы нам ingress контроллер был доступен из Интернета. Для этого с помощью утилиты kubectl редактируем service/ingress-nginx и добавляем в него список публичных IP адресов worker/master нод нашего Кубернетес кластера (только те, которые мы хотим использовать для обработки входящих запросов из Интернета).
$ kubectl -n ingress-nginx edit service/ingress-nginx
и добавляем следующий раздел в YAML манифест
spec:
externalIPs:
- X.X.X.X
- Y.Y.Y.Y
Добавляем А записи в ваш домен и ждем пока информация о них появится в ДНС. Например:
Type: A
Name: echo.example.com
Value: X.X.X.X
Если в ingress-nginx.yaml вы указали несколько внешних IP адресов, то можно создать несколько одинаковых DNS записей с этими IP адресами. В этом случае запросы на ваш домен будут распределяться между этими IP адресами и будет происходить балансировка нагрузки.
В данном примере для работы https сгенерируем самоподписанный SSL сертификат.
$ openssl req -newkey rsa:2048 -nodes -keyout echo.example.com.key -x509 -days 365 -out echo.example.com.crt
Generating a 2048 bit RSA private key
..+++
.............+++
writing new private key to 'echo.example.com.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:UA
State or Province Name (full name) [Some-State]:Kyiv
Locality Name (eg, city) []:Kyiv
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Super Company Ltd
Organizational Unit Name (eg, section) []:echo.example.com
Common Name (e.g. server FQDN or YOUR name) []:echo.example.com
Email Address []:info@echo.example.com
$ cat echo.example.com.key | base64 | tr -d '\n'
<YOUR PRIVATE KEY>
$ cat echo.example.com.crt | base64 | tr -d '\n'
<YOUR CERTIFICATE>
Теперь добавляем наше приложение. В качестве примера выбран простой echoserver. Создаем файл с именем app.yaml и следующим содержимым:
apiVersion: v1
kind: Namespace
metadata:
name: echoserver
---
apiVersion: v1
kind: Secret
metadata:
name: echo.example.com-tls
namespace: echoserver
type: kubernetes.io/tls
data:
tls.crt: <YOUR CERTIFICATE>
tls.key: <YOUR PRIVATE KEY>
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echoserver
namespace: echoserver
spec:
replicas: 1
selector:
matchLabels:
app: echoserver
template:
metadata:
labels:
app: echoserver
spec:
containers:
- image: gcr.io/google_containers/echoserver:1.0
imagePullPolicy: Always
name: echoserver
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: echoserver
namespace: echoserver
spec:
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
selector:
app: echoserver
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: echoserver
namespace: echoserver
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- hosts:
- echo.example.com
secretName: echo.example.com-tls
rules:
- host: echo.example.com
http:
paths:
- path: /
backend:
serviceName: echoserver
servicePort: 80
$ kubectl apply -f app.yaml
namespace "echoserver" configured
deployment "echoserver" unchanged
service "echoserver" configured
ingress "echoserver" unchanged
На этом все )) Проверяем результат:
$ curl https://echo.example.com/
CLIENT VALUES:
client_address=('10.244.3.2', 32860) (10.244.3.2)
command=GET
path=/
real path=/
query=
request_version=HTTP/1.1
SERVER VALUES:
server_version=BaseHTTP/0.6
sys_version=Python/3.5.0
protocol_version=HTTP/1.0
HEADERS RECEIVED:
Accept=*/*
Connection=close
Host=echo.example.com
User-Agent=curl/7.58.0
X-Forwarded-For=10.244.0.0
X-Forwarded-Host=echo.example.com
X-Forwarded-Port=80
X-Forwarded-Proto=http
X-Original-URI=/
X-Real-IP=10.244.0.0
X-Request-ID=7a4f4aabf9a0043ea2b1ca91bd1a3adf
X-Scheme=http