ãã®èšäºã§ã¯ãHashicorpã®SwarmãKubernetesãããã³Nomadã«æ祚ããDockerã¢ããªã±ãŒã·ã§ã³ããããã€ããŸãã ãã®ãã¹ãŠãè©ŠããŠã¿ãã®ãšåããããããã®èšäºãèªãã§æ¥œããã§ãã ããã
ãã¯ãããžãŒã䜿çšããå Žåã¯ã奜å¥å¿ãå¿ èŠã§ãã ããã¯ãçŸå Žã§äœãèµ·ãã£ãŠããããåžžã«åŠã³ãææ°ã®ç¶æ ã«ä¿ã€ããã«å¿ èŠã§ãã ãã¹ãŠãéåžžã«éãå€åããŸãã
ã³ã³ãããªãŒã±ã¹ãã¬ãŒã·ã§ã³ã¯è°è«ã®å¯Ÿè±¡ãšããŠéåžžã«ããããªãããã¯ã§ããããããæ°ã«å ¥ãã®æ¥œåšããã£ããšããŠããä»ã®æ¥œåšãã©ã®ããã«æ©èœãããããã«ã€ããŠæ°ããããšãåŠã¶ã®ã¯èå³æ·±ãããšã§ãã
æ祚ã¢ããª
以åã®èšäºã§æ祚ã¢ããªã䜿çšããŸããã ã¢ããªã±ãŒã·ã§ã³ã¯ãã€ã¯ããµãŒãã¹ã¢ãŒããã¯ãã£ã§å®è¡ããã5ã€ã®ãµãŒãã¹ã§æ§æãããŠããŸãã
![ç»å](https://habrastorage.org/getpro/habr/post_images/83a/dc9/fae/83adc9fae997e0fa89535dab867e2f7b.png)
- æ祚ïŒãŠãŒã¶ãŒãç¬ãšç«ãéžæã§ããããã³ããšã³ã
- RedisïŒé³å£°ããŒã¿ããŒã¹
- ã¯ãŒã«ãŒïŒå€§æ ¹ããæ祚ãåéããçµæãPostgresããŒã¿ããŒã¹ã«ä¿åãããµãŒãã¹
- DbïŒæ祚çµæãä¿åããPostgresããŒã¿ããŒã¹
- çµæïŒããã³ããšã³ãã¯æ祚çµæã衚瀺ããŸã
githubãªããžããªã«ããããã«ãã¢ããªã±ãŒã·ã§ã³ã«ã¯ããã€ãã®æ§æãã¡ã€ã«ããããŸãïŒ https : //github.com/dockersamples/example-voting-app
Docker-stack.yml-ã¢ããªã±ãŒã·ã§ã³ã®æ¬çªãã¬ãŒã³ããŒã·ã§ã³ã§äœ¿çšããæºåãã§ããŸããã ãã¡ã€ã«èªäœã¯æ¬¡ã®ãšããã§ãã
version: "3" services: redis: image: redis:alpine ports: - "6379" networks: - frontend deploy: replicas: 1 update_config: parallelism: 2 delay: 10s restart_policy: condition: on-failure db: image: postgres:9.4 volumes: - db-data:/var/lib/postgresql/data networks: - backend deploy: placement: constraints: [node.role == manager] vote: image: dockersamples/examplevotingapp_vote:before ports: - 5000:80 networks: - frontend depends_on: - redis deploy: replicas: 2 update_config: parallelism: 2 restart_policy: condition: on-failure result: image: dockersamples/examplevotingapp_result:before ports: - 5001:80 networks: - backend depends_on: - db deploy: replicas: 1 update_config: parallelism: 2 delay: 10s restart_policy: condition: on-failure worker: image: dockersamples/examplevotingapp_worker networks: - frontend - backend deploy: mode: replicated replicas: 1 labels: [APP=VOTING] restart_policy: condition: on-failure delay: 10s max_attempts: 3 window: 120s placement: constraints: [node.role == manager] visualizer: image: dockersamples/visualizer:stable ports: - "8080:8080" stop_grace_period: 1m30s volumes: - "/var/run/docker.sock:/var/run/docker.sock" deploy: placement: constraints: [node.role == manager] networks: frontend: backend: volumes: db-data:
éåžžããã®ãã¡ã€ã«ã«ã¯6ã€ã®ãµãŒãã¹ããããã¢ããªã±ãŒã·ã§ã³ã¢ãŒããã¯ãã£ã«ã¯5ã€ã®ãµãŒãã¹ãããããŸããè¿œå ã®ãµãŒãã¹ã¯ããµãŒãã¹ãå±éãããŠããå Žæã瀺ãã€ã³ã¿ãŒãã§ã€ã¹ãæäŸããåªããããŒã«ã§ããããžã¥ã¢ã©ã€ã¶ãŒã§ãã
Docker swarm
Docker Swarmã¯ãDockerã³ã³ãããŒã®ã¯ã©ã¹ã¿ãŒã管çããã³äœæããããã®ããŒã«ã§ãã 管çè ãšéçºè ã¯ãSwarmã䜿çšããŠãããŒãã®ã¯ã©ã¹ã¿ãŒãåäžã®ä»®æ³ã·ã¹ãã ãšããŠäœæããã³ç®¡çã§ããŸãã
Swarmã³ã³ããŒãã³ã
Swarmã¯ã©ã¹ã¿ãŒã¯ããã€ãã®ããŒãã§æ§æãããäžéšã¯ãããŒãžã£ãŒãšããŠæ©èœããä»ã¯ãšã°ãŒãã¥ãŒã¿ãŒãšããŠæ©èœããŸãã
- 管çããŒãã¯ã¯ã©ã¹ã¿ãŒã®å éšç¶æ ãæ åœããŸã
- ããŒãã®å®è¡ã¯ã¿ã¹ã¯ãå®è¡ããŸãïŒ=ã³ã³ãããŒã®èµ·åïŒ
![ç»å](https://habrastorage.org/getpro/habr/post_images/dab/383/312/dab383312018e2076c575b54508f76e7.png)
ãããŒãžã£ãŒã¯ãå éšåæ£ã¹ãã¬ãŒãžãå ±æããŠãäžè²«ããã¯ã©ã¹ã¿ãŒç¶æ ãç¶æããŸãã ããã¯ãRaftãã°ã«ãã£ãŠç¢ºèªãããŸãã
Swarmã§ã¯ããµãŒãã¹ã¯ã¢ããªã±ãŒã·ã§ã³ã®ãããã€æ¹æ³ãšã³ã³ããå ã§ã®åäœæ¹æ³ãå®çŸ©ããŸãã
Dockerãã€ã³ã¹ããŒã«ãã
DockerããŸã ã€ã³ã¹ããŒã«ãããŠããªãå Žåã¯ãOSçšã®Docker CEïŒCommunity EditionïŒãããŠã³ããŒãã§ããŸã ã
Swarmãäœæãã
Dockerãã€ã³ã¹ããŒã«ãããšã1ã€ã®ããŒã ã ããSwarmã®å®è¡ããç§ãã¡ãåé¢ããŸã
$ docker swarm init
Swarmã¯ã©ã¹ã¿ãŒã«å¿ èŠãªã®ã¯ããã ãã§ãã ããã¯åäžããŒãã®ã¯ã©ã¹ã¿ãŒã§ãããé¢é£ãããã¹ãŠã®ããã»ã¹ãæã€ã¯ã©ã¹ã¿ãŒã®ãŸãŸã§ãã
ã¢ããªã±ãŒã·ã§ã³ã®å±é
githubã®ã¢ããªã±ãŒã·ã§ã³ãªããžããªã§å©çšå¯èœãªæ§æãã¡ã€ã«ã®ãã¡ãSwarmãä»ããŠã¢ããªã±ãŒã·ã§ã³ããããã€ããã«ã¯docker-stack.ymlãå¿ èŠã§ãã
$ docker stack deploy -c docker-stack.yml app Creating network app_backend Creating network app_default Creating network app_frontend Creating service app_visualizer Creating service app_redis Creating service app_db Creating service app_vote Creating service app_result Creating service app_worker
ã¹ã¿ãã¯ã¯ãããŒã®ããã«ãŒã§å®è¡ãããŠãããããããŒã«ã«ãã·ã³ããããã«ã¢ããªã±ãŒã·ã§ã³ã«ã¢ã¯ã»ã¹ã§ããŸãã æ祚ã€ã³ã¿ãŒãã§ãŒã¹ïŒããŒã5000ïŒã䜿çšããŠç«ãŸãã¯ç¬ãéžæããããŒã5001ã§çµæã確èªã§ããŸãã
![ç»å](https://habrastorage.org/getpro/habr/post_images/d76/bd4/a97/d76bd4a9778ff0b767d2a0cc2ea21f69.png)
![ç»å](https://habrastorage.org/getpro/habr/post_images/3f2/7a9/552/3f27a955267a8580f88fca12b9be7011.png)
ããã§ã¯è©³çŽ°ã«ç«ã¡å ¥ãããSwarmã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ãç°¡åã«ãããã€ã§ããããšã瀺ãããã£ãã ãã§ãã
è€æ°ã®ããŒãã䜿çšããŠSwarmãä»ããŠã¢ããªã±ãŒã·ã§ã³ããããã€ããæ¹æ³ã®è©³çŽ°ãªèª¬æãå¿ èŠãªå Žåã¯ã ãã®èšäºãèªãããšãã§ããŸãã
ã¯ãã«ããã¹
Kubernetesã¯ãã³ã³ããåãããã¢ããªã±ãŒã·ã§ã³ã®å±éãã¹ã±ãŒãªã³ã°ãããã³ç®¡çãèªååããããã®ãªãŒãã³ãœãŒã¹ãã©ãããã©ãŒã ã§ãã
Kubernetes Concept
Kubernetesã¯ã©ã¹ã¿ãŒã¯ã1ã€ä»¥äžã®ãã¹ã¿ãŒãšããŒãã§æ§æãããŸãã
- ãŠã£ã¶ãŒãã¯ãã¯ã©ã¹ã¿ãŒã®ç®¡çïŒã¯ã©ã¹ã¿ãŒã®ç¶æ ã®ç®¡çãã¿ã¹ã¯ã®ã¹ã±ãžã¥ãŒãªã³ã°ãã¯ã©ã¹ã¿ãŒå ã®ã€ãã³ããžã®å¿çãªã©ïŒãæ åœããŸãã
- ããŒãïŒä»¥åã¯ãããªã³ãšåŒã°ããŠããŸãããã¯ãã挫ç»ãæªçã°ã«ãŒã®ææ³¥æ£ãã®ããã«ïŒã¯ãã¢ããªã±ãŒã·ã§ã³ã³ã³ãããŒãèµ·åããããã®ã©ã³ã¿ã€ã ãæäŸããŸãïŒãããçµç±ïŒ
![ç»å](https://habrastorage.org/getpro/habr/post_images/6a8/f39/fb3/6a8f39fb39514033d7da84ec7a7ba79a.png)
ã³ãã³ããå ¥åããã«ã¯ãkubectl CLIã䜿çšããŸãã 以äžã§ã¯ãããã€ãã®äœ¿çšäŸãæ€èšããŸãã
ã¢ããªã±ãŒã·ã§ã³ã®ãããã€æ¹æ³ãç解ããã«ã¯ãããã€ãã®é«ã¬ãã«ã®Kubernetesãªããžã§ã¯ãã«ã€ããŠç¥ãå¿ èŠããããŸãã
- ãããã¯ãããŒãã«å±éã§ããæå°åäœã§ãã ããã¯ãé£æºããŠåäœããã³ã³ããã®ã°ã«ãŒãã§ãã ãã ããPodã«ã¯ã³ã³ããã1ã€ã ãå«ãŸããŠããããšããããããŸãã
- ReplicaSetã¯ãç¹å®ã®æ°ã®çåºã¬ããªã«ãæäŸããŸãã
- Deploymentã¯ReplicaSetã管çããããŒãªã³ã°ã¢ããããŒãããã«ãŒ/ã°ãªãŒã³ãããã€ã¡ã³ãããã¹ããªã©ãå¯èœã«ããŸãã
- ãµãŒãã¹ã¯ãããŒã¹ã®è«çã»ãããšãããã«ã¢ã¯ã»ã¹ããããã®ããªã·ãŒãå®çŸ©ããŸãã
ãã®ããŒãã§ã¯ãã¢ããªã±ãŒã·ã§ã³ãµãŒãã¹ããšã«å±éãšãµãŒãã¹ã䜿çšããŸãã
kubectlãã€ã³ã¹ããŒã«ãã
Kubectlã¯ãKubernetesã§ã¢ããªã±ãŒã·ã§ã³ãå±éããã³ç®¡çããããã®ã³ãã³ãã©ã€ã³ã§ãã
ã€ã³ã¹ããŒã«ã«ã¯ãå ¬åŒããã¥ã¡ã³ãïŒhttps://kubernetes.io/docs/tasks/tools/install-kubectl/ïŒã䜿çšããŸãã ããšãã°ãMacã«ã€ã³ã¹ããŒã«ããã«ã¯ã次ã®ã³ãã³ããå ¥åããŸãã
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl
$ chmod +x ./kubectl
$ sudo mv ./kubectl /usr/local/bin/kubectl
ãããã¥ãŒãã®ã€ã³ã¹ããŒã«
Minicubeã¯Kubenetesã®å æ¬çãªèšå®ã§ãã ããŒã«ã«VMãäœæãããã¹ãŠã®Kubernetesããã»ã¹ãå®è¡ãããŠããããŒãã¯ã©ã¹ã¿ãŒãèµ·åããŸãã ééããªããããã¯éçšã¯ã©ã¹ã¿ãã€ã³ã¹ããŒã«ããããã«äœ¿çšãã¹ãããŒã«ã§ã¯ãããŸããããéçºãšãã¹ãã«äœ¿çšãããšæ¬åœã«äŸ¿å©ã§ãã
Minicubeãã€ã³ã¹ããŒã«ãããšã1ã€ã®ããŒãã§ã¯ã©ã¹ã¿ãŒãã€ã³ã¹ããŒã«ããããã«å¿ èŠãªã³ãã³ãã¯1ã€ã ãã§ãã
$ minikube start
Starting local Kubernetes v1.7.0 clusterâŠ
Starting VMâŠ
Downloading Minikube ISO
97.80 MB / 97.80 MB [==============================================] 100.00% 0s
Getting VM IP addressâŠ
Moving files into clusterâŠ
Setting up certsâŠ
Starting cluster componentsâŠ
Connecting to clusterâŠ
Setting up kubeconfigâŠ
Kubectl is now configured to use the cluster.
èšè¿°åKubernetes
Kubernetesã§ã¯ã Deploymentã«ãã£ãŠå¶åŸ¡ãããReplicaSetãä»ããŠã³ã³ãããŒãèµ·åãããŸãã
以äžã¯Deploymentã説æãã.ymlãã¡ã€ã«ã®äŸã§ãã ReplicaSetã¯ã2ã€ã®Nginxã¬ããªã«ã®èµ·åãæäŸããŸãã
// nginx-deployment.yml apiVersion: apps/v1beta1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 2 # tells deployment to run 2 pods matching the template template: # create pods using pod definition in this template metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80
å±éãäœæããã«ã¯ãkubectl CLIã䜿çšããå¿ èŠããããŸãã
ãã€ã¯ããµãŒãã¹ã§æ§æãããã¢ããªã±ãŒã·ã§ã³ãäœæããã«ã¯ããµãŒãã¹ããšã«å±éãã¡ã€ã«ãäœæããå¿ èŠããããŸãã ããã¯æåã§è¡ãããšãã Komposeã䜿çšããããšãã§ããŸãã
Komposeã䜿çšããŠãããã€ã¡ã³ããšãµãŒãã¹ãäœæãã
Komposeã¯ãDockeræ§æãã¡ã€ã«ãKubernetesã䜿çšããèšè¿°åãã¡ã€ã«ã«å€æããããŒã«ã§ãã ãã®ãµãŒãã¹ã®æ¹ã䟿å©ã§ã移è¡ããã»ã¹ãé«éåããŸãã
泚ïŒ
Komposeã¯ãªãã·ã§ã³ã§ããã¹ãŠãæåã§äœæã§ããŸãããå±éããã»ã¹ãå€§å¹ ã«é«éåããŸã
- Komposeã¯ãDocker Composeãã¡ã€ã«ã§äœ¿çšããããã¹ãŠã®ãªãã·ã§ã³ãèæ ®ããŸããã
- Komposeã¯ã次ã®ã³ãã³ãã䜿çšããŠLinuxãŸãã¯Macã«ã€ã³ã¹ããŒã«ã§ããŸãã
# Linux
$ curl -L https://github.com/kubernetes/kompose/releases/download/v1.0.0/kompose-linux-amd64 -o kompose
# macOS
$ curl -L https://github.com/kubernetes/kompose/releases/download/v1.0.0/kompose-darwin-amd64 -o kompose
$ chmod +x kompose
$ sudo mv ./kompose /usr/local/bin/kompose
Komposeã§docker -stack.ymlãéå§ããåã«ãå°ãå€æŽããŠåãµãŒãã¹ã®ãããã€ããŒãåé€ããŸãã ãã®ããŒã¯èªèãããªããããèšè¿°åãã¡ã€ã«ã®çææã«ãšã©ãŒãçºçããå ŽåããããŸãã ãããã¯ãŒã¯ã«é¢ããæ å ±ãåé€ããããšãã§ããŸãã Komposeã§ã¯ãdocker -stack-k8s.ymlãåŒã³åºãæ°ãããã¡ã€ã«ãæäŸããŸãã
version: "3" services: redis: image: redis:alpine ports: - "6379" db: image: postgres:9.4 volumes: - db-data:/var/lib/postgresql/data vote: image: dockersamples/examplevotingapp_vote:before ports: - 5000:80 depends_on: - redis result: image: dockersamples/examplevotingapp_result:before ports: - 5001:80 depends_on: - db worker: image: dockersamples/examplevotingapp_worker visualizer: image: dockersamples/visualizer:stable ports: - "8080:8080" stop_grace_period: 1m30s volumes: - "/var/run/docker.sock:/var/run/docker.sock" volumes: db-data:
docker-stack-k8s.ymlãã¡ã€ã«ããã次ã®ã³ãã³ãã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ã®èšè¿°åãçæããŸãã
$ kompose convert --file docker-stack-k8s.yml
WARN Volume mount on the host "/var/run/docker.sock" isn't supported - ignoring path on the host
INFO Kubernetes file "db-service.yaml" created
INFO Kubernetes file "redis-service.yaml" created
INFO Kubernetes file "result-service.yaml" created
INFO Kubernetes file "visualizer-service.yaml" created
INFO Kubernetes file "vote-service.yaml" created
INFO Kubernetes file "worker-service.yaml" created
INFO Kubernetes file "db-deployment.yaml" created
INFO Kubernetes file "db-data-persistentvolumeclaim.yaml" created
INFO Kubernetes file "redis-deployment.yaml" created
INFO Kubernetes file "result-deployment.yaml" created
INFO Kubernetes file "visualizer-deployment.yaml" created
INFO Kubernetes file "visualizer-claim0-persistentvolumeclaim.yaml" created
INFO Kubernetes file "vote-deployment.yaml" created
INFO Kubernetes file "worker-deployment.yaml" created
åãµãŒãã¹ã«ã€ããŠãå±éãã¡ã€ã«ãšãµãŒãã¹ãäœæãããããšãããããŸãã
èŠåã¯1ã€ã ãåãåããŸããã Dockerãœã±ããã«æ¥ç¶ã§ããªãããã ããžã¥ã¢ã©ã€ã¶ãŒãšæ¥ç¶ãããŸãã ãã®ãµãŒãã¹ã®éå§ã¯è©Šã¿ãŸããããæ®ãã«çŠç¹ãåãããŸãã
ã¢ããªã±ãŒã·ã§ã³ã®å±é
kubectlã䜿çšããŠãèšè¿°åãã¡ã€ã«ã§æå®ããããã¹ãŠã®ã³ã³ããŒãã³ããäœæããŸãã ãã¡ã€ã«ãçŸåšã®ãã©ã«ããŒã«ããããšã瀺ããŸãã
$ kubectl create -f .
persistentvolumeclaim "db-data" created
deployment "db" created
service "db" created
deployment "redis" created
service "redis" created
deployment "result" created
service "result" created
persistentvolumeclaim "visualizer-claim0" created
deployment "visualizer" created
service "visualizer" created
deployment "vote" created
service "vote" created
deployment "worker" created
service "worker" created
unable to decode "docker-stack-k8s.yml":...
泚ïŒå€æŽããæ§æãã¡ã€ã«ãçŸåšã®ãã©ã«ããŒã«æ®ããããã解æã§ããªããããšã©ãŒãçºçããŸããã ãããããã®ééãã¯ãªã¹ã¯ãªãã§ç¡èŠã§ããŸãã
ãããã®ã³ãã³ãã䜿çšãããšãäœæããããµãŒãã¹ãšãããã€ã¡ã³ãã確èªã§ããŸãã
![ç»å](https://habrastorage.org/getpro/habr/post_images/38d/6af/b43/38d6afb43a4cee5602f9e092f1f52a77.jpg)
å€ã®äžçããã¢ããªã±ãŒã·ã§ã³ã«ã¢ã¯ã»ã¹ã§ããããã«ããŸã
æ祚ãšçµæã®ã€ã³ã¿ãŒãã§ãŒã¹ã«ã¢ã¯ã»ã¹ããã«ã¯ããããã®ããã«äœæããããµãŒãã¹ããããã«å€æŽããå¿ èŠããããŸãã
æ祚çšã«çæãããèšè¿°åã¯æ¬¡ã®ãšããã§ãã
apiVersion: v1 kind: Service metadata: creationTimestamp: null labels: io.kompose.service: vote name: vote spec: ports: - name: "5000" port: 5000 targetPort: 80 selector: io.kompose.service: vote status: loadBalancer: {}
ãµãŒãã¹ã®ã¿ã€ããå€æŽãã ClusterIPãNodePortã«çœ®ãæããŸãã ClusterIPã¯ãµãŒãã¹ãå éšã§å©çšå¯èœã«ãã NodePortã¯ããŒããã¯ã©ã¹ã¿ãŒã®åããŒãã§å ¬éããäžçäžã§å©çšã§ããããã«ããŸãã æ祚ãšçµæã®äž¡æ¹ã«å€éšããã¢ã¯ã»ã¹ã§ããããã«ãããã ã resultã«å¯ŸããŠãåãããšãè¡ããŸãã
apiVersion: v1 kind: Service metadata: labels: io.kompose.service: vote name: vote spec: type: NodePort ports: - name: "5000" port: 5000 targetPort: 80 selector: io.kompose.service: vote
äž¡æ¹ã®ãµãŒãã¹ïŒ æ祚ãšçµæ ïŒã«å€æŽãå ããããããããåäœæã§ããŸãã
$ kubectl delete svc vote
$ kubectl delete svc result
$ kubectl create -f vote-service.yaml
service "vote" created
$ kubectl create -f result-service.yaml
service "result" created
ã¢ããªã±ãŒã·ã§ã³ãžã®ã¢ã¯ã»ã¹
次ã«ã æ祚ããã³çµæãµãŒãã¹ã®è©³çŽ°ãååŸããããããæäŸããããŒããååŸããŸãã
![ç»å](https://habrastorage.org/getpro/habr/post_images/fa4/ef5/fec/fa4ef5fec0825c7bd92faafb5c01483c.jpg)
æ祚ã¯ããŒã30069ã§å©çšã§ãã çµæã¯31873ã§ããä»åºŠã¯æ祚ããŠçµæã確èªããŸãã
![ç»å](https://habrastorage.org/getpro/habr/post_images/831/e3c/dd4/831e3cdd4ddae53a267bbe469bb6baef.png)
![ç»å](https://habrastorage.org/getpro/habr/post_images/e8b/5d0/7ba/e8b5d07baeee81a86ae7b58ecdc6c5b5.png)
Kubernetesã®åºæ¬ã³ã³ããŒãã³ããç解ããåŸãã¢ããªã±ãŒã·ã§ã³ãç°¡åã«ãããã€ã§ããŸããã Komposeã¯ç§ãã¡ã倧ãã«å©ããŠãããŸããã
ãã·ã³ãŒãã®éç§æ°
Nomadã¯ããã·ã³ã®ã¯ã©ã¹ã¿ãŒã管çãããããã§ã¢ããªã±ãŒã·ã§ã³ãå®è¡ããããã®ããŒã«ã§ãã ãã·ã³ãšã¢ããªã±ãŒã·ã§ã³ãã¹ããæœè±¡åãããŠãŒã¶ãŒãå®è¡ãããããšãèšãããšãã§ããããã«ããŸãã ãããŠãNomadã¯ããããã©ãã§ã©ã®ããã«èµ·åããããã«ã€ããŠè²¬ä»»ãè² ããŸãã
ãããã³ã³ã»ãã
Nomadã¯ã©ã¹ã¿ãŒã¯ã ãµãŒã㌠ïŒãµãŒããŒïŒã¢ãŒããŸãã¯ã¯ã©ã€ã¢ã³ã ïŒã¯ã©ã€ã¢ã³ãïŒã¢ãŒãã§åäœã§ãããšãŒãžã§ã³ãã§æ§æãããŠããŸãã
- ãµãŒããŒã¯ã³ã³ã»ã³ãµã¹ãããã³ã«ãæ åœããŸã ãããã«ããããµãŒããŒã¯ãªãŒããŒãéžæããç¶æ ãè€è£œã§ããŸãã
- ã¯ã©ã€ã¢ã³ãã¯ãµãŒããŒãšå¯Ÿè©±ããããéåžžã«è»œéã§ãããã¯ã©ã€ã¢ã³ãèªäœã¯ã»ãšãã©äœãããŸããã ã¯ã©ã€ã¢ã³ãããŒãã¯ã¿ã¹ã¯ãå®è¡ããŸãã
![ç»å](https://habrastorage.org/getpro/habr/post_images/c9d/c09/d85/c9dc09d852f4490132512719c5792a11.png)
Nomadã¯ã©ã¹ã¿ãŒã§ã¯ãããã€ãã®ã¿ã€ãã®ã¿ã¹ã¯ãèµ·åã§ããŸãã
ã¢ããªã±ãŒã·ã§ã³ããããã€ããã«ã¯ãNomadã®åºæ¬æŠå¿µãç解ããå¿ èŠããããŸãã
- ãžã§ã-Nomadãå®è¡ããã¿ã¹ã¯ã決å®ããŸãã ããã¯ããžã§ããã¡ã€ã«ïŒhclããã¹ããã¡ã€ã«ãHashicorpæ§æèšèªïŒã§èª¬æãããŠããŸãã ãžã§ãã«ã¯1ã€ä»¥äžã®ã¿ã¹ã¯ã°ã«ãŒããå«ãŸããå ŽåããããŸãã
- ã°ã«ãŒãã«ã¯ãåããã·ã³äžã«ããããã€ãã®ã¿ã¹ã¯ãå«ãŸããŸãã
- ã¿ã¹ã¯-å®è¡äžã®ããã»ã¹ããã®å Žåã¯Dockerã³ã³ãããŒ
- ãžã§ãå ã®ã¿ã¹ã¯ã®ãããã³ã°ã¯ãå²ãåœãŠã䜿çšããŠè¡ãããŸãã å²ãåœãŠã¯ããžã§ãå ã®ã¿ã¹ã¯ãç¹å®ã®ããŒãã§å®è¡ãããããã«ããããã«äœ¿çšãããŸãã
èšçœ®
ãã®äŸã§ã¯ãDocker Machineã䜿çšããŠäœæãããDockerãã¹ãã§ã¢ããªã±ãŒã·ã§ã³ãå®è¡ããŸãã ããŒã«ã«IP-192.168.1.100ã ãŸããConsulãå®è¡ããŸããConsulã¯ããµãŒãã¹ã®æ€åºãšç»é²ã«äœ¿çšãããŸãã Nomadãèµ·åããã¢ããªã±ãŒã·ã§ã³ãJob in NomadãšããŠãããã€ããŸãã
ãµãŒãã¹ã®ç»é²ãšçºèŠã®ããã®é äº
ãµãŒãã¹ãæ€åºããŠç»é²ããã«ã¯ãNomadã®Jobã®ããã«æ©èœããªãConsulãªã©ã®ããŒã«ããå§ãããŸãã é äºã¯ãªã³ã¯ããããŠã³ããŒãã§ããŸãã
ãã®ã³ãã³ãã¯ãConsulãµãŒããŒãããŒã«ã«ã§èµ·åããŸãã
$ consul agent -dev -client=0.0.0.0 -dns-port=53 -recursor=8.8.8.8
䜿çšããããªãã·ã§ã³ã詳ããèŠãŠã¿ãŸãããã
- -devã¯ããµãŒããŒãšã¯ã©ã€ã¢ã³ãã§Consulã¯ã©ã¹ã¿ãŒãèšå®ãããã©ã°ã§ãã ãã®ãªãã·ã§ã³ã¯ãéçºãšãã¹ãã«ã®ã¿äœ¿çšããŠãã ããã
- -client = 0.0.0.0ã䜿çšãããšããã¹ãã€ã³ã¿ãŒãã§ã€ã¹ãä»ããŠConsulãµãŒãã¹ïŒAPIããã³DNSãµãŒããŒïŒã«å°éã§ããŸãã ããã¯ãNomadãlocalhostã€ã³ã¿ãŒãã§ã€ã¹ãä»ããŠConsulã«æ¥ç¶ããdocker-bridgeïŒ172.17.x.xãªã©ïŒãä»ããŠã³ã³ããã«æ¥ç¶ããããã«å¿ èŠã§ãã
- -dns-port = 53ã¯ãConsul DNSãµãŒããŒã䜿çšããããŒããå®çŸ©ããŸãïŒããã©ã«ãã¯8600ïŒã DNSãã³ã³ãããã䜿çšã§ããããã«ãæšæºã®53ããŒããã€ã³ã¹ããŒã«ããŸãã
- -recursor = 8.8.8.8ã¯ãConsulãåŠçã§ããªãèŠæ±ãåŠçããå¥ã®DNSãµãŒããŒãå®çŸ©ããŸã
Nomadã¯ãã®ãªã³ã¯ããããŠã³ããŒãã§ããŸãã
ããŒããæã€ã¯ã©ã¹ã¿ãŒãäœæãã
NomadãããŠã³ããŒããããã次ã®èšå®ã§ãšãŒãžã§ã³ããèµ·åã§ããŸãã
// nomad.hcl bind_addr = "0.0.0.0" data_dir = "/var/lib/nomad" server { enabled = true bootstrap_expect = 1 } client { enabled = true network_speed = 100 }
ãšãŒãžã§ã³ãã¯ãµãŒããŒãšã¯ã©ã€ã¢ã³ãã®äž¡æ¹ãšããŠæ©èœããŸãã bind_addrã¯ãã¿ã¹ã¯ãå€éšããåãå ¥ããããšãã§ããããã«ãã©ã®ã€ã³ã¿ãŒãã§ã€ã¹ã§ãåäœããå¿ èŠãããããšãææããŸãã 次ã®èšå®ã§Nomad Agentãèµ·åããŸãã
$ nomad agent -config=nomad.hcl
==> WARNING: Bootstrap mode enabled! Potentially unsafe operation.
Loaded configuration from nomad-v2.hcl
==> Starting Nomad agent...
==> Nomad agent configuration:
Client: true
Log Level: INFO
Region: global (DC: dc1)
Server: true
Version: 0.6.0
==> Nomad agent started! Log data will stream in below:
泚ïŒããã©ã«ãã§ã¯ãNomadã¯ããŒã«ã«ã®Consulã€ã³ã¹ã¿ã³ã¹ã«æ¥ç¶ããŸãã
åäžããŒãã¯ã©ã¹ã¿ãŒãã€ã³ã¹ããŒã«ããŸããã äžæã®ã¡ã³ããŒã«é¢ããæ å ±ã¯æ¬¡ã®ãšããã§ãã
$ nomad server-members
Name Address Port Status Leader Protocol Build Datacenter Region
neptune.local.global 192.168.1.100 4648 alive true 2 0.6.0 dc1 global
ã¢ããªã±ãŒã·ã§ã³ã®å±é
Swarmã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ããããã€ããã«ã¯ãããã«æ§æãã¡ã€ã«ã䜿çšã§ããŸãã Kubernetesãä»ããŠãããã€ããã«ã¯ãåãæ§æãã¡ã€ã«ããã®èšè¿°åãå¿ èŠã§ãã ããã¯ãã¹ãŠãNomadãéããŠã©ã®ããã«è¡ãããŸããïŒ
ãŸããKompose for Hashicorpã«äŒŒãããŒã«ã¯ãããŸããããã®ãããã³ã³ãã®Nomadãžã®ç§»è¡ãç°¡åã«ããããšãã§ããŸãïŒã¡ãªã¿ã«ããªãŒãã³ãœãŒã¹ãããžã§ã¯ãã«ãšã£ãŠã¯è¯ãèãã§ãïŒã Jobs ã groups ã tasksãèšè¿°ãããã¡ã€ã«ã¯æåã§äœæããå¿ èŠããããŸãã
ããã«ã€ããŠã¯ã Redisããã³VoteãµãŒãã¹ã®ãžã§ãã«ã€ããŠèª¬æããéã«è©³ããèŠãŠãããŸãã ä»ã®ãµãŒãã¹ã«ã€ããŠã¯ããã®ããã«ãªããŸãã
Redisã®ãžã§ãã®å®çŸ©
ãã®ãã¡ã€ã«ã¯ãã¢ããªã±ãŒã·ã§ã³ã®Redisã®äžéšãå®çŸ©ããŸãã
// redis.nomad job "redis-nomad" { datacenters = ["dc1"] type = "service" group "redis-group" { task "redis" { driver = "docker" config { image = "redis:3.2" port_map { db = 6379 } } resources { cpu = 500 # 500 MHz memory = 256 # 256MB network { mbits = 10 port "db" {} } } service { name = "redis" address_mode = "driver" port = "db" check { name = "alive" type = "tcp" interval = "10s" timeout = "2s" } } } } }
ããã«äœãæžãããŠãããèŠãŠã¿ãŸãããïŒ
- ãžã§ãå-redis-nomad
- ãžã§ãã®çš®é¡-ãµãŒãã¹ïŒã€ãŸããé·æéã®æäœïŒ
- ã°ã«ãŒãã«ã¯ä»»æã®ååãä»ããããŸãã 1ã€ã®æäœãå«ã
- ã¿ã¹ã¯Redisã¯docker-driverã䜿çšããŸããã€ãŸããã³ã³ãããŒã§å®è¡ãããŸãã
- ã¿ã¹ã¯ã¯Redisã€ã¡ãŒãžã䜿çšããŸãïŒ3.2
- ãªãœãŒã¹ãå«ããããã¯ã§ã¯ãCPUãšã¡ã¢ãªã®å¶éã瀺ãããŸãã
- ãããã¯ãŒã¯ãããã¯ã¯ãdbããŒããåçã§ãªããã°ãªããªãããšã瀺ããŸã
- ãµãŒãã¹ãããã¯ã¯ãConsulã®ç»é²æ¹æ³ãå®çŸ©ããŸãããµãŒãã¹ã®ååãIPã¢ãã¬ã¹ãããã³ãã«ã¹ãã§ãã¯ã®å®çŸ©
ãžã§ããæ£ããå®è¡ããããã©ããã確èªããã«ã¯ã planã³ãã³ãã䜿çšããŸãã
$ nomad plan redis.nomad + Job: "nomad-redis" + Task Group: "cache" (1 create) + Task: "redis" (forces create) Scheduler dry-run: - All tasks successfully allocated. Job Modify Index: 0 To submit the job with version verification run: nomad run -check-index 0 redis.nomad When running the job with the check-index flag, the job will only be run if the server side version matches the job modify index returned. If the index has changed, another user has modified the job and the plan's results are potentially invalid.
ãã¹ãŠãæ©èœããŠããããã§ãã 次ã«ããã®ãžã§ãã䜿çšããŠã¿ã¹ã¯ãå±éããŸãã
$ nomad run redis.nomad ==> Monitoring evaluation "1e729627" Evaluation triggered by job "nomad-redis" Allocation "bf3fc4b2" created: node "b0d927cd", group "cache" Evaluation status changed: "pending" -> "complete" ==> Evaluation "1e729627" finished with status "complete"
ãã¬ãŒã¹ã¡ã³ããäœæãããããšãããããŸãã 圌ã®ã¹ããŒã¿ã¹ã確èªããŠãã ããïŒ
$ nomad alloc-status bf3fc4b2 ID = bf3fc4b2 Eval ID = 1e729627 Name = nomad-redis.cache[0] Node ID = b0d927cd Job ID = nomad-redis Job Version = 0 Client Status = running Client Description = <none> Desired Status = run Desired Description = <none> Created At = 08/23/17 21:52:03 CEST Task "redis" is "running" Task Resources CPU Memory Disk IOPS Addresses 1/500 MHz 6.3 MiB/256 MiB 300 MiB 0 db: 192.168.1.100:21886 Task Events: Started At = 08/23/17 19:52:03 UTC Finished At = N/A Total Restarts = 0 Last Restart = N/A Recent Events: Time Type Description 08/23/17 21:52:03 CEST Started Task started by client 08/23/17 21:52:03 CEST Task Setup Building Task Directory 08/23/17 21:52:03 CEST Received Task received by client
ã³ã³ããã¯æ£ããèµ·åãããŠããŸãã Consul DNSãµãŒããŒããã§ãã¯ããŠããµãŒãã¹ãæ£ããç»é²ãããŠããããšã確èªããŸãããã
$ dig @localhost SRV redis.service.consul ; <<>> DiG 9.10.3-P4-Ubuntu <<>> @localhost SRV redis.service.consul ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35884 ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;redis.service.consul. IN SRV ;; ANSWER SECTION: redis.service.consul. 0 IN SRV 1 1 6379 ac110002.addr.dc1.consul. ;; ADDITIONAL SECTION: ac110002.addr.dc1.consul. 0 IN A 172.17.0.2 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Wed Aug 23 23:08:36 CEST 2017 ;; MSG SIZE rcvd: 103
ã¿ã¹ã¯ã¯IP 172.17.0.2ã«ãã£ãŠãã¹ãããããã®ããŒãã¯å ã«ç€ºããããã«6379ã§ãã
æ祚ã®ããã®ä»äºã®å®çŸ©
æ祚ãµãŒãã¹ã®ãžã§ããå®çŸ©ããŸãã 次ã®ãã¡ã€ã«ã䜿çšããŸãã
// job.nomad job "vote-nomad" { datacenters = ["dc1"] type = "service" group "vote-group" { task "vote" { driver = "docker" config { image = "dockersamples/examplevotingapp_vote:before" dns_search_domains = ["service.dc1.consul"] dns_servers = ["172.17.0.1", "8.8.8.8"] port_map { http = 80 } } service { name = "vote" port = "http" check { name = "vote interface running on 80" interval = "10s" timeout = "5s" type = "http" protocol = "http" path = "/" } } resources { cpu = 500 # 500 MHz memory = 256 # 256MB network { port "http" { static = 5000 } } } } } }
ãã ããRedisã«äœ¿çšãããã¡ã€ã«ãšã¯ããã€ãã®éãããããŸãã
- æ祚ã¯æäœåã®ã¿ã䜿çšããŠredisã«æ¥ç¶ããŸãã æ祚ãµãŒãã¹ã§äœ¿çšãããapp.pyãã¡ã€ã«ã®äžéšã®äŸã次ã«ç€ºããŸãã
// app.py def get_redis(): if not hasattr(g, 'redis'): g.redis = Redis(host="redis", db=0, socket_timeout=5) return g.redis
ãã®å Žåã redisã䜿çšããŠIPã³ã³ãããŒãååŸããã«ã¯ ã æ祚㮠ããã³ã³ãããŒãConsul DNSãµãŒããŒã䜿çšããå¿ èŠããããŸãã ã³ã³ããããã®DNSã¯ãšãªã¯ãDockerããªããžïŒ172.17.0.1ïŒãä»ããŠå®è¡ãããŸãã dns_search_domainsã¯ããµãŒãã¹XãConsulå ã®X.service.dc1.consulãšããŠç»é²ãããŠããããšãå€å¥ããŸã
- ããŒã5000ã®æ祚ãµãŒãã¹ãã¯ã©ã¹ã¿ãŒã®å€éšããã¢ã¯ã»ã¹ã§ããããã«ãéçããŒããèšå®ããŸãã
ä»ã®ãµãŒãã¹ã«å¯ŸããŠåãèšå®ãè¡ãããšãã§ããŸãïŒworkerãpostgresãresultã
ã¢ããªã±ãŒã·ã§ã³ãžã®ã¢ã¯ã»ã¹
ãã¹ãŠã®ãžã§ããå®è¡ãããŠããå Žåããžã§ãã®ã¹ããŒã¿ã¹ã確èªãããã¹ãŠãæ©èœããããšã確èªã§ããŸãã
![ç»å](https://habrastorage.org/getpro/habr/post_images/158/ac1/2cc/158ac12cc671e9044fdfe4ec2b39e916.jpg)
ããã¯ãConsulã€ã³ã¿ãŒãã§ãŒã¹ã§ãèŠãããšãã§ããŸãã
![ç»å](https://habrastorage.org/getpro/habr/post_images/f7e/797/f16/f7e797f1615e9ea3935abdb7e615fc2a.png)
IPããŒãïŒãã®äŸã§ã¯192.168.1.100ïŒ ã«ãã ã voteããã³resultã䜿çšããŠã€ã³ã¿ãŒãã§ãŒã¹ã«ã¢ã¯ã»ã¹ã§ããŸãã
ãŸãšã
ããã«ããã®ãããªæ祚æ祚ããã¢ã³ã¹ãã¬ãŒã·ã§ã³ã®é¢ã§çŽ æŽãããã¢ããªã±ãŒã·ã§ã³ã§ãã ãªãŒã±ã¹ãã©ã䜿çšããŠã³ãŒããå€æŽããã«å±éã§ãããã©ãããç¥ããããšæããŸããã ã¯ããã¿ã³ããªã³ãšã®ç¹å¥ãªãã³ã¹ããªããŠãã§ããŸãã
ãã®èšäºãSwarmãKubernetesãNomadã®åºæ¬ãç解ããã®ã«åœ¹ç«ã€ããšãé¡ã£ãŠããŸãã ãŸããDockerã§èµ·åããŠãããã®ãšãªãŒã±ã¹ãã©ã®äœ¿çšæ¹æ³ãç¥ãããšãèå³æ·±ãã§ãããã