Je dois augmenter le cluster Kubernetes, mais je ne suis qu'un programmeur de code. Il y a un moyen de sortir



Bonjour. Une autre note de mon expérience. Cette fois, c'est superficiel sur l'infrastructure de base, que j'utilise si je dois décharger quelque chose, mais il n'y a pas de gars devOps à proximité . Mais le niveau d'abstraction actuel, en technologie, permet de vivre environ un an avec cette infrastructure, élevée la nuit, en utilisant Internet et des choses toutes faites.

Mots clés - AWS + Terraform + kops . Si cela m'est utile, ce sera probablement utile à quelqu'un d'autre. Bienvenue dans les commentaires.

-1. Ce que nous avons affaire


La situation classique - le projet est écrit à un tel stade quand il est nécessaire de le décharger quelque part et de commencer à l'utiliser. Et le projet est plus compliqué qu'une simple page html. Je souhaite la possibilité d'une mise à l'échelle horizontale, l'identité de l'environnement sur des stands locaux, de test, de produits et un processus de déploiement plus ou moins normal.
Il s'agit d'une application sur Laravel pour montrer tout le processus du début à la fin. Mais de la même manière, vous pouvez déployer une dispersion de services en cours, des applications python, de petits sites sur WP, des pages html et bien plus encore. À un certain niveau, cela suffit, puis une personne distincte apparaît dans l'équipe, qui l'améliorera et la complétera.
Récemment, je suis venu au fait que j'installe GoLand, PhpStorm, Docker, Git sur des machines locales et je suis complètement prêt à travailler. Oui, et vous pouvez gérer à partir d'une seule machine dans des clusters en vrac, donc je vais décrire tout le processus sans prendre en compte le système d'exploitation sur lequel vous travaillez, en emballant toutes choses dans un conteneur Docker.

0. Se préparer au travail.


Imaginons que nous ayons déjà enregistré un compte sur AWS , demandé par le support technique d'augmenter les limites de compte par le nombre de serveurs exécutés simultanément, créé un utilisateur IAM et maintenant nous avons Access Key + Secret Key . Zone - us-east-1 .

De quoi avons-nous besoin sur l'ordinateur local? AWS CLI , Terraform pour la gestion déclarative d' AWS , kubectl , kops pour la configuration du cluster et Helm , pour le déploiement de certains services. Nous récupérons le Dockerfile (que j'ai trouvé il y a longtemps quelque part dans l'immensité du github, mais je ne trouve pas où). Nous écrivons notre docker-compose.yml pour les répertoires de montage et Makefile pour les alias.

Dockerfile
FROM ubuntu:16.04 ARG AWSCLI_VERSION=1.12.1 ARG HELM_VERSION=2.8.2 ARG ISTIO_VERSION=0.6.0 ARG KOPS_VERSION=1.9.0 ARG KUBECTL_VERSION=1.10.1 ARG TERRAFORM_VERSION=0.11.0 # Install generally useful things RUN apt-get update \ && apt-get -y --force-yes install --no-install-recommends \ curl \ dnsutils \ git \ jq \ net-tools \ ssh \ telnet \ unzip \ vim \ wget \ && apt-get clean \ && apt-get autoclean \ && apt-get autoremove \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* # Install AWS CLI RUN apt-get update \ && apt-get -y --force-yes install \ python-pip \ && pip install awscli==${AWSCLI_VERSION} \ && apt-get clean \ && apt-get autoclean \ && apt-get autoremove \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* # Install Terraform RUN wget -O terraform.zip https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip \ && unzip terraform.zip \ && mv terraform /usr/local/bin/terraform \ && chmod +x /usr/local/bin/terraform \ && rm terraform.zip # Install kubectl ADD https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VERSION}/bin/linux/amd64/kubectl /usr/local/bin/kubectl RUN chmod +x /usr/local/bin/kubectl # Install Kops ADD https://github.com/kubernetes/kops/releases/download/${KOPS_VERSION}/kops-linux-amd64 /usr/local/bin/kops RUN chmod +x /usr/local/bin/kops # Install Helm RUN wget -O helm.tar.gz https://storage.googleapis.com/kubernetes-helm/helm-v${HELM_VERSION}-linux-amd64.tar.gz \ && tar xfz helm.tar.gz \ && mv linux-amd64/helm /usr/local/bin/helm \ && chmod +x /usr/local/bin/helm \ && rm -Rf linux-amd64 \ && rm helm.tar.gz # Create default user "kops" RUN useradd -ms /bin/bash kops WORKDIR /home/kops USER kops # Ensure the prompt doesn't break if we don't mount the ~/.kube directory RUN mkdir /home/kops/.kube \ && touch /home/kops/.kube/config 

docker-compose.yml
 version: '2.1' services: cluster-main: container_name: cluster.com image: cluster.com user: root stdin_open: true volumes: - ./data:/data - ./.ssh:/root/.ssh - ./.kube:/root/.kube - ./.aws:/root/.aws cluster-proxy: container_name: cluster.com-kubectl-proxy image: cluster.com user: root entrypoint: kubectl proxy --address='0.0.0.0' --port=8001 --accept-hosts='.*' ports: - "8001:8001" stdin_open: true volumes: - ./data:/data - ./.ssh:/root/.ssh - ./.kube:/root/.kube - ./.aws:/root/.aws 

Makefile
 docker.build: docker build -t cluster.com . docker.run: docker-compose up -d docker.bash: docker exec -it cluster.com bash 


Dockerfile - prenez l'image ubuntu de base et installez tous les logiciels. Makefile - juste pour plus de commodité, vous pouvez utiliser le mécanisme habituel des alias. Docker-compose.yml - nous avons ajouté un conteneur supplémentaire qui nous jettera dans le navigateur du tableau de bord K8S si vous avez besoin de voir visuellement quelque chose.

Nous créons les dossiers data , .ssh , .kube , .aws à la racine et y mettons notre configuration pour les clés aws, ssh et nous pouvons collecter et exécuter notre conteneur via make docker.build & make docker.run .

Eh bien, dans le dossier de données , créez un dossier dans lequel nous mettons les fichiers yaml k8s , et à côté du second, dans lequel nous allons stocker l'état de la terraforme du cluster. Je mets le résultat approximatif de cette étape sur le github .

1. Élevez notre cluster.


Ensuite, une traduction gratuite de cette note sera disponible. Je vais omettre de nombreux points théoriques, essayer de décrire une brève compression. Tout de même, le format de ma note est tldr.

Dans notre dossier data / aws-cluster-init-kops-terraform, nous clonons ce qui se trouve dans ce référentiel et accédons à la console du conteneur via make docker.bash . La dispersion des équipes ennuyeuses commence.

CLI AWS


Nous créons l'utilisateur kops , ajoutons des droits d'accès et reconfigurons l' AWS CLI afin de ne pas exécuter de commandes à partir du superutilisateur.

 aws iam create-group --group-name kops #   aws iam attach-group-policy --policy-arn arn:aws:iam::aws:policy/AmazonEC2FullAccess --group-name kops aws iam attach-group-policy --policy-arn arn:aws:iam::aws:policy/AmazonRoute53FullAccess --group-name kops aws iam attach-group-policy --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess --group-name kops aws iam attach-group-policy --policy-arn arn:aws:iam::aws:policy/IAMFullAccess --group-name kops aws iam attach-group-policy --policy-arn arn:aws:iam::aws:policy/AWSCertificateManagerFullAccess --group-name kops aws iam attach-group-policy --policy-arn arn:aws:iam::aws:policy/AmazonVPCFullAccess --group-name kops aws iam create-user --user-name kops aws iam add-user-to-group --user-name kops --group-name kops aws iam create-access-key --user-name kops 

 aws configure 

Initialiser Terraform


Dans le fichier data / aws-cluster-init-kops-terraform / variables.tf, remplacez le nom du cluster par celui souhaité. N'oubliez pas de prendre nos serveurs DNS à partir du fichier update.json et de les mettre à jour là où vous avez acheté votre domaine.

 #    cd /data/aws-cluster-init-kops-terraform #    AWS CLI export AWS_ACCESS_KEY_ID=$(aws configure get aws_access_key_id) export AWS_SECRET_ACCESS_KEY=$(aws configure get aws_secret_access_key) #  terraform terraform init terraform get terraform apply #  NS  cat update-zone.json \ | jq ".Changes[].ResourceRecordSet.Name=\"$(terraform output name).\"" \ | jq ".Changes[].ResourceRecordSet.ResourceRecords=$(terraform output -json name_servers | jq '.value|[{"Value": .[]}]')" \ > update-zone.json 

Kops


Nous créons un cluster via kops , en exportant la configuration dans un fichier .tf .

 export NAME=$(terraform output cluster_name) export KOPS_STATE_STORE=$(terraform output state_store) export ZONES=$(terraform output -json availability_zones | jq -r '.value|join(",")') kops create cluster \ --master-zones $ZONES \ --zones $ZONES \ --topology private \ --dns-zone $(terraform output public_zone_id) \ --networking calico \ --vpc $(terraform output vpc_id) \ --target=terraform \ --out=. \ ${NAME} 

Une petite remarque s'impose ici. Terraform créera un VPC , et nous devrons modifier légèrement la configuration que nous donnera Kops . Cela se fait tout simplement via l'image d'assistance ryane / gensubnets: 0.1
 #   terraform output -json > subnets.json 

 #     echo subnets.json | docker run --rm -i ryane/gensubnets:0.1 

Vous pouvez ajouter des politiques immédiates pour route53.

 additionalPolicies: master: | [ { "Effect": "Allow", "Action": ["route53:ListHostedZonesByName"], "Resource": ["*"] }, { "Effect": "Allow", "Action": ["elasticloadbalancing:DescribeLoadBalancers"], "Resource": ["*"] }, { "Effect": "Allow", "Action": ["route53:ChangeResourceRecordSets"], "Resource": ["*"] } ] node: | [ { "Effect": "Allow", "Action": ["route53:ListHostedZonesByName"], "Resource": ["*"] }, { "Effect": "Allow", "Action": ["elasticloadbalancing:DescribeLoadBalancers"], "Resource": ["*"] }, { "Effect": "Allow", "Action": ["route53:ChangeResourceRecordSets"], "Resource": ["*"] } ] 

Modification via le kops edit cluster $ {NAME} .



Maintenant, nous pouvons augmenter le cluster lui-même.

 kops update cluster \ --out=. \ --target=terraform \ ${NAME} terraform apply 

Tout ira bien, le contexte de kubectl va changer. Dans le dossier data / aws-cluster-init-kops-terraform , nous stockons l'état du cluster. Vous pouvez simplement tout mettre dans git et l'envoyer dans un dépôt bitpack privé.

 $ kubectl get nodes NAME STATUS AGE ip-10-20-101-252.ec2.internal Ready,master 7m ip-10-20-103-232.ec2.internal Ready,master 7m ip-10-20-103-75.ec2.internal Ready 5m ip-10-20-104-127.ec2.internal Ready,master 6m ip-10-20-104-6.ec2.internal Ready 5m 

2. Augmentez notre application


Maintenant que nous avons quelque chose, nous pouvons déployer nos services dans un cluster. Je mettrai des configurations approximatives dans le même référentiel . Ils peuvent être placés dans un paquet en data / k8s .

Blagues de service


Commençons par le service. Nous avons besoin de barre , de route53 , de classes de stockage et d'un accès à notre registre privé sur hub.docker.com . Eh bien, ou à tout autre, s'il y a un tel désir.

 # Init helm kubectl create serviceaccount --namespace kube-system tiller kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}' helm init 

 kubectl apply -f default-namespace.yaml kubectl apply -f storage-classes.yaml kubectl apply -f route53.yaml kubectl apply -f docker-hub-secret.yml kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml 

PostgreSQL + Redis


J'ai brûlé tant de fois en utilisant Docker, pas pour des conteneurs sans état , mais la dernière configuration s'est jusqu'à présent révélée la plus appropriée. J'utilise Stolon pour fournir une évolutivité. Environ un an, le vol est normal.

Nous déployons des diagrammes de barre et quelques configurations rapides de Redis .

 #  etcd  stolon cd etcd-chart helm install --name global-etcd . #   stolon cd stolon-chart helm dep build helm install --name global-postgres . #  redis kubectl apply -f redis 

Nginx + php


Le bouquet habituel. Nginx et php-fpm . Je n'ai pas particulièrement nettoyé les configurations, mais tout le monde peut configurer pour lui-même. Avant de postuler, vous devez spécifier l'image à partir de laquelle nous prendrons le code + ajouter une ligne de certificat à partir d' AWS Certificate Manager . Php lui-même - vous pouvez le prendre depuis le dockerhab, mais j'ai construit mon privé en ajoutant quelques bibliothèques.

 kubectl apply -f nginx kubectl apply -f php 

Dans notre image avec le code, nous le stockons dans le dossier / crm-code . Nous le remplaçons par votre image et cela fonctionnera assez correctement. Le fichier est nginx / deployment.yml .



Faites ressortir le domaine. Le service Route53 le récupérera, modifiera / ajoutera des enregistrements DNS, le certificat sera téléchargé sur ELB depuis AWS Certificate Manager . Le fichier est nginx / service.yml .



Transférer les variables env en php pour les avoir à l'intérieur et se connecter à PostgreSQL / Redis . Le fichier est php / deployment.yml .



En conséquence, nous avons un cluster K8S qui, à un niveau de base, nous pouvons évoluer, ajouter de nouveaux services, de nouveaux serveurs (nœuds), modifier le nombre d'instances PostgreSQL, PHP, Nginx et vivre avant qu'une personne distincte n'apparaisse dans l'équipe qui le fera .

Dans le cadre de cette courte note, je n'aborderai pas les problèmes de sauvegarde / surveillance de tout cela. Au stade initial, localhost sera suffisant : 8001 / ui du service K8S Dashboard . Plus tard, il sera possible de fixer Prometheus , Grafana , Barman ou toute autre solution similaire.

En utilisant un terminal ou Teamcity , Jenkins mettant à jour le code fera quelque chose comme ça.

 #     -      Teamcity docker build -t GROUP/crm-code:latest . docker push GROUP/crm-code:latest #   (  ) kubectl set image deployment/php-fpm php-fpm=GROUP/php-fpm kubectl rollout status deployment/php-fpm kubectl set image deployment/php-fpm php-fpm=GROUP/php-fpm:latest kubectl set image deployment/nginx nginx=danday74/nginx-lua kubectl rollout status deployment/nginx kubectl set image deployment/nginx nginx=danday74/nginx-lua:latest kubectl rollout status deployment/php-fpm kubectl rollout status deployment/nginx 

Je serais heureux si ce serait intéressant pour quelqu'un et doublement heureux si cela aide quelqu'un. Merci de votre attention. Encore une fois, j'attache un lien vers le référentiel un et deux .

Source: https://habr.com/ru/post/fr423481/


All Articles