Kubernetes - открытое программное обеспечение для автоматизации развёртывания, масштабирования контейнеризированных приложений и управления ими. Оригинальная версия была разработана компанией Google для внутренних нужд, впоследствии система передана под управление Cloud Native Computing Foundation. В Kubernetes все описывается при помощи yaml-файлов.
Концепции Kubernetes:
Контроллер (controller) — это процесс, который управляет состоянием кластера, пытаясь привести его от фактического к желаемому; он делает это, оперируя набором подов, который определяется с помощью селекторов меток, являющихся частью определения контроллера[20]. Выполнение контроллеров обеспечивается компонентом Kubernetes Controller Manager. Один из типов контроллеров, самый известный — это контроллер репликации (Replication Controller), который обеспечивает масштабирование, запустив указанное количество копий пода в кластере. Он также обеспечивает запуск новых экземпляров пода, в том случае если узел, на котором работает управляемый этим контроллером под, выходит из строя. Другие контроллеры, входящие в основную систему Kubernetes, включают в себя «DaemonSet Controller», который обеспечивает запуск пода на каждой машине (или подмножеством машин) и «Job Controller» для запуска подов, которые выполняются до завершения, например, как часть пакетного задания.
Kubernetes предоставляет ряд средств для интеграции процессов разработки и развёртывания программного обеспечения, работающего под управлением этой системы. Среди наиболее часто используемых в этих целях инструментов:
Команды kubectl:
# Отразить api-resources kubectl api-resources # отразить запущенные nodes kubectl get nodes # отразить deployments kubectl get deployments # отразить services kubectl get services # отразить запущенные pods kubectl get pods # Подробнее kubectl describe pod/[namesPOD] # запустить образ на порту 8080 kubectl run hello-minikube --image=gcr.io/google_containers/echoserver:1.4 --port=8080 # открыть внешний IP для hello-minikube kubectl expose deployment hello-minikube --type=NodePort # delete service,deployment hello-minikube kubectl delete service,deployment hello-minikube # Работа с configmaps: kubectl get configmaps kubectl get configmap {имя карты конфигурации} -o yaml kubectl edit configmap {имя конфигурации карты} kubectl get cm {имя карты конфигурации} -o = yaml --export> filename.yaml # manifests: kubectl create -f deploy/kubernetes/manifests-logging (тут YML файлы) kubectl --namespace=kube-system get pods kubectl --namespace=kube-system get deploy,rs,pods
Разбираем namespaces:
kubectl get namespaces NAME STATUS AGE default Active 39m kube-node-lease Active 39m kube-public Active 39m kube-system Active 39m kubernetes-dashboard Active 39m
Чтобы создать отдельный namespaces, создадим файл json "namespace-dev.json и namespace-prod.json":
# nano namespace-dev.json # nano namespace-prod.json { "kind": "Namespace", "apiVersion": "v1", "metadata": { "name": "development", "labels": { "name": "development" } } }
запускаем:
kubectl apply -f namespace-dev.json namespace/development created kubectl get namespaces --show-labels NAME STATUS AGE LABELS default Active 20m <none> development Active 14m name=development kube-node-lease Active 20m <none> kube-public Active 20m <none> kube-system Active 20m <none> kubernetes-dashboard Active 20m addonmanager.kubernetes.io/mode=Reconcile,kubernetes.io/minikube-addons=dashboard
Аналогично можно создать Prod намеспейс "production".
Проверим текущий конфиг (nano ~/.kube/config):
kubectl config view apiVersion: v1 clusters: - cluster: certificate-authority: /home/debuser/.minikube/ca.crt server: https://192.168.99.105:8443 name: minikube contexts: - context: cluster: minikube user: minikube name: minikube current-context: minikube kind: Config preferences: {} users: - name: minikube user: client-certificate: /home/debuser/.minikube/client.crt client-key: /home/debuser/.minikube/client.key
Для создания контекста, проверяем текущий:
kubectl config current-context minikube
Создаем context, данные "cluster и user" взяты из вывода выше (стандартные):
kubectl config set-context dev --namespace=development \ --cluster=minikube \ --user=minikube
Переключиться на нужный:
kubectl config use-context dev Switched to context "dev".
Чтобы делать какие-то действия с конкретным namespaces:
kubectl --namespace=dev get pods или kubectl --namespace=prod run nginx --image=nginx
* При создании "Service" создаеться DNS запись, нужно использовать полное доменное имя, иначе достучаться можно только в рамках неймспейса.
kubectl --namespace=kube-system get deployments NAME READY UP-TO-DATE AVAILABLE AGE coredns 2/2 2 2 18m elasticsearch 0/1 1 0 3m16s kibana 1/1 1 1 3m16s nginx-ingress-controller 1/1 1 1 17m kubectl --namespace=kube-system get rs NAME DESIRED CURRENT READY AGE coredns-5644d7b6d9 2 2 2 17m elasticsearch-8476b9f4c6 1 1 0 2m41s kibana-5dd9f95469 1 1 0 2m41s nginx-ingress-controller-6fc5bcc8c9 1 1 1 17m kubectl --namespace=kube-system get nodes NAME STATUS ROLES AGE VERSION minikube Ready master 17m v1.16.2
API versioning
* Подробнее: kubernetes.io/docs/concepts/overview/kubernetes-api/
# отразить api-resources kubectl api-resources NAME SHORTNAMES APIGROUP NAMESPACED KIND ... configmaps cm true ConfigMap namespaces ns false Namespace pods po true Pod daemonsets ds apps true DaemonSet deployments deploy apps true Deployment replicasets rs apps true ReplicaSet ingresses ing extensions true Ingress ingresses ing networking.k8s.io true Ingress
Заголовки:
kubectl api-versions apps/v1 batch/v1 extensions/v1beta1 rbac.authorization.k8s.io/v1 scheduling.k8s.io/v1beta1 ...
Команды для minikube:
minikube start minikube stop minikube config set memory 6144 minikube start --memory 8192 --cpus 4 minikube start -p <name> minikube ssh minikube status minikube ip minikube service hello-minikube --url curl $(minikube service hello-minikube --url) # addons minikube: minikube addons list minikube addons enable <name> minikube addons disable <name>
* Настройка minikube: habr.com/ru/company/flant/blog/333470
* addons minikube: minikube.sigs.k8s.io/docs/tasks/addons/
Пример запуска minikube:
minikube start * minikube v1.5.2 on Debian 10.1 * Tip: Use 'minikube start -p <name>' to create a new cluster, or 'minikube delete' to delete this one. * Starting existing virtualbox VM for "minikube" ... * Waiting for the host to be provisioned ... * Preparing Kubernetes v1.16.2 on Docker '18.09.9' ... * Relaunching Kubernetes using kubeadm ... * Waiting for: apiserver * Done! kubectl is now configured to use "minikube"
Типичные ошибки minikube:
Ошибка №1:
unable to recognize "deploy/kubernetes/manifests-logging/elasticsearch.yml": no matches for kind "Deployment" in version "extensions/v1beta1"
Ответ: в YML файле стоит "apiVersion: extensions/v1beta1", а надо "apiVersion: apps/v1". Нужно исправить в заголовке файла.
Ошибка №2:
serviceaccounts "fluentd" already exists
[error validating "deploy/kubernetes/manifests-logging/elasticsearch.yml": error validating data: ValidationError(Deployment.spec): missing required field "selector" in io.k8s.api.apps.v1.DeploymentSpec; if you choose to ignore these errors, turn validation off with --validate=false, unable to recognize "deploy/kubernetes/manifests-logging/fluentd-daemon.yml": no matches for kind "DaemonSet" in version "extensions/v1beta1", error validating "deploy/kubernetes/manifests-logging/kibana.yml": error validating data: ValidationError(Deployment.spec): missing required field "selector" in io.k8s.api.apps.v1.DeploymentSpec; if you choose to ignore these errors, turn validation off with --validate=false]
Ответ: если перевести дословно, то получается, что ошибка "ValidationError" в разделе "Deployment" подразделе "spec" (полный путь Deployment.spec). Ошибка в отсутствии или неверном указании "selector". В нашем случае его просто нет.
Пример верного исполнения:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80
Для исправления ошибки надо указать такой фрагмент:
selector: matchLabels: app: nginx
* внимание на app, у нас в файле было "name" вместо "app".
Ошибка №3:
deployments.apps "kibana" already exists
Error from server (Invalid): error when creating "deploy/kubernetes/manifests-logging/kibana.yml": Service "kibana" is invalid: spec.ports[0].nodePort: Invalid value: 31601: provided port is already allocated
unable to recognize "deploy/kubernetes/manifests-logging/fluentd-daemon.yml": no matches for kind "DaemonSet" in version "extensions/v1beta1"
+ Доп.Инфа по ошибке:
kubectl get pods --namespace=kube-system NAME READY STATUS RESTARTS AGE elasticsearch-869b79886f-td95m 0/1 ImagePullBackOff 0 8m11s kibana-779c44ff4d-pv6vw 0/1 ImagePullBackOff 0 13m kube-ingress-dns-minikube 1/1 Running 0 31m nginx-ingress-controller-6fc5bcc8c9-bgcwb 1/1 Running 0 31m
* Так как я тестировал на minikube, то там есть addons, в частности я активировал enable "minikube addons list":
Ответ: в очевидной форме его нет, но есть следующее "spec.ports[0].nodePort: Invalid value: 31601: provided port is already allocated". Отсюда делаем вывод, что ошибка в этой части кода:
... spec: type: NodePort ports: - port: 5601 targetPort: 5601 nodePort: 31601 ...
* Обратимся к официальной документации по Ingress: kubernetes.io/docs/concepts/services-networking/ingress/
Используем шаблон и вставим его в наш файл после основного кода "---":
"deploy/kubernetes/manifests-logging/kibana.yml"
... --- apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: test-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - http: paths: - path: /testpath backend: serviceName: test servicePort: 80
Дальше исправляем под логику файла.
Разберем пример кода:
Основа:
apiVersion: v1 kind: Pod metadata: ... spec: ...
Заполним:
apiVersion: v1 # Минимальная единица: один или несколько контейнеров kind: Pod # Метаданные: metadata: name: kibana-pod labels: app: kibana # Спецификация: spec: containers: - name: kibana image: elk/kibana
Подключим Volumes:
apiVersion: v1 # Минимальная единица: один или несколько контейнеров kind: Pod # Метаданные: metadata: name: kibana-pod labels: app: kibana # Спецификация: spec: containers: - name: kibana image: elk/kibana # volumes для этого образа, который источник volumemaps берет из общего значения volumeMounts: - name: kibana-config # Куда смонтировать конфигмеп при запуске контейнера mountPath: /etc/kibana/conf.d # Общий volumes volumes: - name: kibana-config configMap: name: kibana-config
Меняем Pod на ReplicaSet:
apiVersion: v1 # Меняем Pod на ReplicaSet kind: ReplicaSet metadata: name: kibana-pod labels: app: kibana # --- вставка --- spec: # Параметры для ReplicaSet replicas: 3 # selector по какому критерию выделять pod. Выбор по matchLabel. Если их меньше 3, создает нужное кол. selector: matchLabel: app: kibana # Шаблон по которому создавать реплику. Описание pod'а template: metadata: labels: app: kibana # --- конец --- spec: containers: - name: kibana image: elk/kibana volumeMounts: - name: kibana-config mountPath: /etc/kibana/conf.d volumes: - name: kibana-config configMap: name: kibana-config
Примеры вывода разных комманд:
kubectl --namespace=kube-system get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE elasticsearch ClusterIP 10.96.000.000 <none> 9200/TCP 11m kibana ClusterIP 10.98.00.00 <none> 31601/TCP 11m kube-dns ClusterIP 10.96.0.00 <none> 53/UDP,53/TCP,9153/TCP 19m
kubectl --namespace=kube-system get pods NAME READY STATUS RESTARTS AGE coredns-5644d7b6d9-nn8f7 1/1 Running 0 20m coredns-5644d7b6d9-p4ftw 1/1 Running 0 20m elasticsearch-8476b9f4c6-8dhkc 0/1 ImagePullBackOff 0 12m etcd-minikube 1/1 Running 0 19m fluentd-wm8dr 0/1 ImagePullBackOff 0 12m kibana-5dd9f95469-bqx57 0/1 ImagePullBackOff 0 12m kube-addon-manager-minikube 1/1 Running 0 20m kube-apiserver-minikube 1/1 Running 0 19m kube-controller-manager-minikube 1/1 Running 0 18m kube-ingress-dns-minikube 1/1 Running 0 4m6s kube-proxy-mn92h 1/1 Running 0 20m kube-scheduler-minikube 1/1 Running 0 19m nginx-ingress-controller-6fc5bcc8c9-lfzmq 1/1 Running 0 4m4s storage-provisioner 1/1 Running 0 4m5s
kubectl --namespace=kube-system get nodes NAME STATUS ROLES AGE VERSION minikube Ready master 20m v1.16.2
DaemonSet ds/StatefulSet sts
kubectl --namespace=kube-system get ds NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE fluentd 1 1 0 1 0 beta.kubernetes.io/os=linux 15m kube-proxy 1 1 1 1 1 beta.kubernetes.io/os=linux 23m
kubectl cluster-info Kubernetes master is running at https://192.168.99.109:8443 KubeDNS is running at https://192.168.99.109:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
kubectl --namespace=kube-system get deployments NAME READY UP-TO-DATE AVAILABLE AGE coredns 2/2 2 2 44m elasticsearch 1/1 1 1 37m kibana 1/1 1 1 37m nginx-ingress-controller 1/1 1 1 28m
kubectl --namespace=kube-system get deployments/elasticsearch -o yaml apiVersion: apps/v1 kind: Deployment metadata: annotations: deployment.kubernetes.io/revision: "1" creationTimestamp: "2019-11-26T12:02:17Z" generation: 1 labels: name: elasticsearch name: elasticsearch namespace: kube-system resourceVersion: "2649" selfLink: /apis/apps/v1/namespaces/kube-system/deployments/elasticsearch uid: 4c9f1628-0dba-4032-9583-38f5035edb74 spec: progressDeadlineSeconds: 600 replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: name: elasticsearch strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: creationTimestamp: null labels: name: elasticsearch spec: containers: - image: elasticsearch:6.8.5 imagePullPolicy: IfNotPresent name: elasticsearch ports: - containerPort: 9200 name: elasticsearch protocol: TCP resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsPolicy: ClusterFirst nodeSelector: beta.kubernetes.io/os: linux restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 status: availableReplicas: 1 conditions: - lastTransitionTime: "2019-11-26T12:20:42Z" lastUpdateTime: "2019-11-26T12:20:42Z" message: Deployment has minimum availability. reason: MinimumReplicasAvailable status: "True" type: Available - lastTransitionTime: "2019-11-26T12:20:42Z" lastUpdateTime: "2019-11-26T12:20:42Z" message: ReplicaSet "elasticsearch-8476b9f4c6" has successfully progressed. reason: NewReplicaSetAvailable status: "True" type: Progressing observedGeneration: 1 readyReplicas: 1 replicas: 1 updatedReplicas: 1
kubectl --namespace=kube-system logs deployments/elasticsearch -f OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release. OpenJDK 64-Bit Server VM warning: UseAVX=2 is not supported on this CPU, setting it to UseAVX=0 [2019-11-26T12:20:49,462][INFO ][o.e.e.NodeEnvironment ] [JkdvrLQ] using [1] data paths, mounts [[/ (overlay)]], net usable_space [11.7gb], net total_space [16.9gb], types [overlay] [2019-11-26T12:20:49,470][INFO ][o.e.e.NodeEnvironment ] [JkdvrLQ] heap size [1015.6mb], compressed ordinary object pointers [true] [2019-11-26T12:20:49,475][INFO ][o.e.n.Node ] [JkdvrLQ] node name derived from node ID [JkdvrLQYTzaz6mig1P4qYA]; set [node.name] to override [2019-11-26T12:20:49,476][INFO ][o.e.n.Node ] [JkdvrLQ] version[6.8.5], pid[1], build[default/docker/78990e9/2019-11-13T20:04:24.100411Z], OS[Linux/4.19.76/amd64], JVM[AdoptOpenJDK/OpenJDK 64-Bit Server VM/13.0.1/13.0.1+9] [2019-11-26T12:20:49,477][INFO ][o.e.n.Node ] [JkdvrLQ] JVM arguments [-Xms1g, -Xmx1g, -XX:+UseConcMarkSweepGC, -XX:CMSInitiatingOccupancyFraction=75, -XX:+UseCMSInitiatingOccupancyOnly, -Des.networkaddress.cache.ttl=60, -Des.networkaddress.cache.negative.ttl=10, -XX:+AlwaysPreTouch, -Xss1m, -Djava.awt.headless=true, -Dfile.encoding=UTF-8, -Djna.nosys=true, -XX:-OmitStackTraceInFastThrow, -Dio.netty.noUnsafe=true, -Dio.netty.noKeySetOptimization=true, -Dio.netty.recycler.maxCapacityPerThread=0, -Dlog4j.shutdownHookEnabled=false, -Dlog4j2.disable.jmx=true, -Djava.io.tmpdir=/tmp/elasticsearch-17964736905779610579, -XX:+HeapDumpOnOutOfMemoryError, -XX:HeapDumpPath=data, -XX:ErrorFile=logs/hs_err_pid%p.log, -Xlog:gc*,gc+age=trace,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m, -Djava.locale.providers=COMPAT, -XX:UseAVX=2, -Des.cgroups.hierarchy.override=/, -Des.path.home=/usr/share/elasticsearch, -Des.path.conf=/usr/share/elasticsearch/config, -Des.distribution.flavor=default, -Des.distribution.type=docker]
Кривое удаление:
kubectl --namespace=kube-system delete deployments/elasticsearch deployment.apps "elasticsearch" deleted
Нормальное удаление:
kubectl --namespace=kube-system delete pod/elasticsearch-8476b9f4c6-gzfq4 pod "elasticsearch-8476b9f4c6-gzfq4" deleted
kubectl --namespace=kube-system get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES coredns-5644d7b6d9-nn8f7 1/1 Running 0 58m 172.00.0.0 minikube <none> <none> coredns-5644d7b6d9-p4ftw 1/1 Running 0 58m 172.00.0.0 minikube <none> <none> elasticsearch-8476b9f4c6-gzfq4 1/1 Running 0 3m28s 172.00.0.0 minikube <none> <none> etcd-minikube 1/1 Running 0 57m 192.168.99.109 minikube <none> <none> fluentd-wm8dr 1/1 Running 0 51m 172.00.0.0 minikube <none> <none> kibana-5dd9f95469-bqx57 1/1 Running 0 51m 172.00.0.0 minikube <none> <none> kube-addon-manager-minikube 1/1 Running 0 58m 192.168.99.109 minikube <none> <none> kube-apiserver-minikube 1/1 Running 0 57m 192.168.99.109 minikube <none> <none> kube-controller-manager-minikube 1/1 Running 0 57m 192.168.99.109 minikube <none> <none> kube-ingress-dns-minikube 1/1 Running 0 42m 192.168.99.109 minikube <none> <none> kube-proxy-mn92h 1/1 Running 0 58m 192.168.99.109 minikube <none> <none> kube-scheduler-minikube 1/1 Running 0 57m 192.168.99.109 minikube <none> <none> nginx-ingress-controller-6fc5bcc8c9-lfzmq 1/1 Running 0 42m 172.00.0.0 minikube <none> <none> storage-provisioner 1/1 Running 0 42m 192.168.99.109 minikube <none> <none>
kubectl --namespace=kube-system describe deployments/elasticsearch Name: elasticsearch Namespace: kube-system CreationTimestamp: Tue, 26 Nov 2019 17:50:16 +0500 Labels: name=elasticsearch Annotations: deployment.kubernetes.io/revision: 1 Selector: name=elasticsearch Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: name=elasticsearch Containers: elasticsearch: Image: elasticsearch:6.8.5 Port: 9200/TCP Host Port: 0/TCP Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: elasticsearch-8476b9f4c6 (1/1 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 5m37s deployment-controller Scaled up replica set elasticsearch-8476b9f4c6 to 1
kubectl --namespace=kube-system get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE elasticsearch ClusterIP 10.00.0.0 <none> 9200/TCP 55m kibana ClusterIP 10.00.0.0 <none> 31601/TCP 55m kube-dns ClusterIP 10.00.0.0 <none> 53/UDP,53/TCP,9153/TCP 62m
Общий вывод:
kubectl --namespace=kube-system get deploy,rs,pods NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/coredns 2/2 2 2 65m deployment.apps/elasticsearch 1/1 1 1 9m39s deployment.apps/kibana 1/1 1 1 57m deployment.apps/nginx-ingress-controller 1/1 1 1 48m NAME DESIRED CURRENT READY AGE replicaset.apps/coredns-5644d7b6d9 2 2 2 64m replicaset.apps/elasticsearch-8476b9f4c6 1 1 1 9m39s replicaset.apps/kibana-5dd9f95469 1 1 1 57m replicaset.apps/nginx-ingress-controller-6fc5bcc8c9 1 1 1 48m NAME READY STATUS RESTARTS AGE pod/coredns-5644d7b6d9-nn8f7 1/1 Running 0 64m pod/coredns-5644d7b6d9-p4ftw 1/1 Running 0 64m pod/elasticsearch-8476b9f4c6-gzfq4 1/1 Running 0 9m39s pod/etcd-minikube 1/1 Running 0 63m pod/fluentd-wm8dr 1/1 Running 0 57m pod/kibana-5dd9f95469-bqx57 1/1 Running 0 57m pod/kube-addon-manager-minikube 1/1 Running 0 65m pod/kube-apiserver-minikube 1/1 Running 0 64m pod/kube-controller-manager-minikube 1/1 Running 0 63m pod/kube-ingress-dns-minikube 1/1 Running 0 48m pod/kube-proxy-mn92h 1/1 Running 0 64m pod/kube-scheduler-minikube 1/1 Running 0 64m pod/nginx-ingress-controller-6fc5bcc8c9-lfzmq 1/1 Running 0 48m pod/storage-provisioner 1/1 Running 0 48m