Kubernetes Engineã§Google Cloudã2ãæé䜿çšããŠããŸãã å®éããã¹ãŠãé ã«å
¥ããã®ã«1ãæã¯ããããŸããã§ããããããã€ãã®ãã©ãã«ã«å¯ŸåŠããã«ã¯åããããããããŸããã
TL; DRïŒGoogleã¯ããªãè¯ãä»äºãããŠããã®ã§ãAWSã¯ãªã©ãã¯ã¹ããŠããŸããã AWSãããç¥ã£ãŠãããªããGoogle Cloudããã¹ãããããšããå§ãããŸãã ç§ã¯çèã®èšæ¶ã®ããã«AWSã«æ
£ããŠãããããããŸããããGoogle CloudãšKubernetesãç 究ããŠãããã»ãšãã©ã®ã·ããªãªã§èªä¿¡ãæã£ãŠããŸãã
ç§ã¯å°é家ã§ã¯ãããŸããã®ã§ãããçšåºŠæççã«ç§ã®èšèãåãå
¥ããŠãã ããã Google CloudãšKubernetesã¯ãç§ãæ¬åœã«è©±ããããããã¯ã®1ã€ã§ãããåžžã«é©åãªèšèãèŠã€ããããšãã§ããããã§ã¯ãããŸãããææ¡ããããœãªã¥ãŒã·ã§ã³ã«ã€ããŠæ£ããã¢ã€ãã¢ãåŸãããšãã§ããã°å¹žãã§ãã
ãã®èšäºã®ç®çã¯ãå°æ¥ã®äœ¿çšã®ããã«ããã€ãã®æçãšæèãä¿åããããšã§ãã ãããã£ãŠãããã¯æ®µéçãªã¬ã€ãã§ã¯ãªãããšã«æ³šæããŠãã ããã æåã¯ã¬ã€ããæžãã€ããã§ããããä»åºŠã¯æ¬å
šäœãæžããããªãã®ã§ããããšã«æ°ã¥ããŸããã
Google CloudãKubernetesãªã©ã§æåããã«ã¯ãååãªçµéšãå¿
èŠã§ãã Linux From Scratchãã€ã³ã¹ããŒã«ããããšããªãå ŽåããµãŒããŒã®æé©åãå®è¡ããããšããªãå ŽåãIronãµãŒããŒã³ã³ããŒãã³ããæ°ã«å
¥ããªãå Žåã¯ãå®éã®éçšå±éãå®è¡ããªãã§ãã ããã æãå®å
šãªè³ãã¯ãŸã Herokuã«ãããŸãã
ããªãã¯ïŒç§ã®ä»¥åã®ããã°ã®ããã«ïŒããããåãã®ã奜ããªäººã§ãªããã°ãªããŸããã
ç§ã¯ãã¹ãŠãç¥ããŸããããååã«ç¥ã£ãŠããŸãã ãŸããå¿
èŠãªãã®ãç解ããå¿
èŠããããŸããã æåã®YAMLãã¡ã€ã«ãäœæããåã«ãããŒãºãè¿°ã¹ãããšãéèŠã§ãã èšç»ã¯éåžžã«éèŠã§ãã
å¿
èŠãªãã®ã¯æ¬¡ã®ãšããã§ãã
- ããŒãªã³ã°æŽæ°ïŒ ããŠã³ã¿ã€ã ãŒãã®æŽæ°çš ïŒãšãµãŒããŒã®èªåããã³æåã®æ°Žå¹³ã¹ã±ãŒãªã³ã°ã®äž¡æ¹ãå®è¡ã§ããã¹ã±ãŒã©ãã«ãªWebã¢ããªã±ãŒã·ã§ã³ã
- èªåã¹ãããã·ã§ãã/ããã¯ã¢ãããåããããŠã³ãå¯èœãªæ°žç¶ã¹ãã¬ãŒãžã
- èªåããã¯ã¢ããããã³èªã¿åãå°çšã€ã³ã¹ã¿ã³ã¹ãžã®ç°¡åãªã¬ããªã±ãŒã·ã§ã³ãåããä¿¡é Œã§ãã管çããŒã¿ããŒã¹ïŒPostgresqlïŒã
- ãããŒãžãã·ãŒã¯ã¬ããã¹ãã¬ãŒãžãœãªã¥ãŒã·ã§ã³ïŒENV HerokuãµããŒããªã©ïŒã ãããã¯ã·ã§ã³æ§æããœãŒã¹ã³ãŒãã«ä¿åããªãã§ãã ããã
- ã«ã¹ã¿ã å±éã€ã³ãã©ã¹ãã©ã¯ãã£ãå¿
èŠãšããªãDockerã€ã¡ãŒãžã®ãµããŒãã
- åºå®IPã¢ãã¬ã¹ãå¿
èŠãšããçµ±åã®ããã®éçå€éšIPã¢ãã¬ã¹ã
- CloudFlareã«æ¥ç¶ã§ããããã«SSLãçµäºããŸãïŒCDNã¯å¿
èŠã§ãããååã§ã¯ãããŸããã2018幎ã«ã¯ãDDoSä¿è·ãå¿
èŠã«ãªããŸãïŒã
- ããã©ã«ãã§ã¯ååãªã»ãã¥ãªãã£ããããŸããã€ãŸããçè«çã«ã¯ãéãããšã決å®ãããŸã§ãã¹ãŠãããã¯ãããŸãã
- ããŒã¿ã»ã³ã¿ãŒã®ããŸããŸãªå°åããã³ãŸãŒã³ã§ã®é«å¯çšæ§ã
ã·ã³ãã«ãªãã¢Webã¢ããªã±ãŒã·ã§ã³ã¯ç°¡åã«ãããã€ã§ããŸãã ããããç§ã¯ãã¢ãæãã§ããŸããã§ãããç§ã¯é·æçã«çç£ã®ããã®ãœãªã¥ãŒã·ã§ã³ãæãã§ããŸããã
ããã€ãã®åå¿è
ã®åé¡ïŒ
- ããã¥ã¡ã³ãã¯éåžžã«åºç¯å²ã§ãããæ¢ããŠãããã®ãç¥ã£ãŠããã°ã»ãšãã©ãã¹ãŠãèŠã€ããããšãã§ããŸãã ãŸããAzureãšAWSã¯Kubernetesã«ããã€ãã®éããå®è£
ããŠãããããäžéšã®ããã¥ã¡ã³ãã¯Google Cloudã«é©çšãããããã®éãåæ§ã§ãã
- ã¢ã«ãã¡ãããŒã¿ãããã³å®å®æ®µéã«ã¯å€ãã®æ©èœããããŸãã ããã¥ã¡ã³ãã¯ç解ã§ããããã«èŠããŸãããã»ãã®æ°ãæåã®ã»ãšãã©ã®ãã¥ãŒããªã¢ã«ã¯ãæå³ãããšããã«åäœããªãå ŽåããããŸãïŒKubernetes 1.8.4-gkeïŒã
- åãæŠå¿µãåç
§ããäžé£ã®åèªããããŸãã èªåœã«æ
£ããå¿
èŠããããŸãã
- ã¬ãŽãæŒå¥ããŠãããšæ³åããŠãã ããã 詳现ã¯ããŸããŸãªæ¹æ³ã§çµã¿åããããå¹²æžãããå¯èœæ§ããããŸããããã¹ãŠãå°ç¡ãã«ããã®ã¯éåžžã«ç°¡åã§ãã ããã¯ãèŠä»¶ãæºããç¬èªã®æ§æãäœæã§ããããšãæå³ããŸãã ãããããã ã³ããŒããããšã¯ã§ããŸããã
- YAMLãã¡ã€ã«ãšã³ãã³ãã©ã€ã³ã䜿çšããŠã»ãŒãã¹ãŠãå®è¡ã§ããŸãããæ§æãåå©çšããããšïŒããšãã°ãäœæ¥ç°å¢ãäžéç°å¢ãªã©ïŒã¯ç°¡åãªäœæ¥ã§ã¯ãããŸããã ãã©ã¡ãŒã¿ãŒåå¯èœã§åå©çšå¯èœãªYAMLããããåŠçãããµãŒãããŒãã£ããŒã«ããããŸãããç§ã¯ãã¹ãŠæåã§è¡ããŸãã ã€ã³ãã©ã¹ãã©ã¯ãã£ã§èªååããããã³ãã¬ãŒããè©ŠããŠã¯ãããŸããããã³ãã¬ãŒãã®æ©èœãæ£ç¢ºã«ç¥ããªãã§ãã ããã
gcloud
ãškubectl
2ã€ã®éãã³ãã³ãã©ã€ã³ããŒã«ãããkubectl
ã
ããäžåºŠæãåºãããŠãã ãããããã¯ã¹ããããã€ã¹ãããã®ã¬ã€ãã§ã¯ãããŸãã ã ããã€ãã®ã¹ãããã«æ³šéãä»ããŸãã
ã¹ã±ãŒã©ãã«ãªWebå±€ïŒWebã¢ããªèªäœïŒ
æåã«å¿
èŠãªã®ã¯ãå®å
šãª12å åã¢ããªã§ãã
Ruby on RailsãDjangoãLaravelãNode.jsïŒãšã«ããïŒã§ãã£ãŠããããã¯å
±æã¢ã¯ã»ã¹ãæãããããŒã«ã«ãã¡ã€ã«ã·ã¹ãã ãžã®æžã蟌ã¿ã«äŸåããªãã¢ããªã±ãŒã·ã§ã³ã§ãªããã°ãªããŸããã ã€ã³ã¹ã¿ã³ã¹ãåå¥ã«ç°¡åã«ç¡å¹ã«ããŠå®è¡ã§ããã¢ããªã±ãŒã·ã§ã³ã ããŒã«ã«ã¡ã¢ãªãŸãã¯ããŒã«ã«ãã¡ã€ã«ã«ã»ãã·ã§ã³ãååšããªãããã«ããå¿
èŠããããŸãïŒã»ãã·ã§ã³ã®è¿æ¥ãé¿ããããšããå§ãããŸãïŒã ããŒã«ã«ãã¡ã€ã«ã·ã¹ãã ãžã®ãã¡ã€ã«ã¢ããããŒãã¯ãããŸããïŒå¿
èŠã«å¿ããŠãå€éšæ°žç¶ã¹ãã¬ãŒãžãããŠã³ãããå¿
èŠããããŸãïŒãåžžã«ããããŒãžãã¹ãã¬ãŒãžãµãŒãã¹ã«ãã€ããªã¹ããªãŒã ãéä¿¡ããããšããå§ãããŸãã
ãã£ã³ã¬ãŒããªã³ãè³ç£ãä»ããŠãã£ãã·ã¥ãåºåããé©åãªãã€ãã©ã€ã³ãå¿
èŠã§ãïŒå¥œããšå¥œãŸãããšã«ããããããRailsã¯Asset Pipelineã§ããã«äœ¿ããæé«ã®ãœãªã¥ãŒã·ã§ã³ãæäŸããŠããŸãïŒã
ã¢ããªã±ãŒã·ã§ã³ãã€ã³ã¹ãã«ã¡ã³ããã New Relic RPMãšRollbarãè¿œå ããŸãã
2018幎ãSQLã€ã³ãžã§ã¯ã·ã§ã³ïŒãŸãã¯ä»ã®å
¥åïŒã䜿çšããŠç¬èªã®ã³ãŒããå±éããããªããã³ãŒãã®åšãã§å¶åŸ¡ãããŠããªãè©äŸ¡ãCSRFãŸãã¯XSSãªã©ã®å ŽæããããŸããã CIã³ã³ãã€ãŒã ç§ã¯åŸ
ã€ããšãã§ããŸã...
ããã¯ãã¥ãŒããªã¢ã«ã§ã¯ãªããããGoogle Cloudã«ç»é²ããŠããããžã§ã¯ããå°åããŸãŒã³ãèšå®ã§ãããšæ³å®ããŠããŸãã
Google Cloudã®äž»èŠãªæ§é ãç解ããã«ã¯å°ãæéãããããŸããã
- ã¢ããªã±ãŒã·ã§ã³ã«å¿
èŠãªãã¹ãŠã®ã«ããŒãšããŠæ©èœãããããžã§ã¯ãããå§ããŸãã
- 次ã«ã ãã¯ã©ã¹ã¿ãŒããäœæããŸãã ããšãã°ããªãã©ã€ã³è³æçšã«ãæ¬çªãã¹ããŒãžã³ã°ã¯ã©ã¹ã¿ãŒãWebã¯ã©ã¹ã¿ãŒããŸãã¯ã¹ããªãããµãŒãã¹ã¯ã©ã¹ã¿ãŒããããšããŸãã
- ã¯ã©ã¹ã¿ãŒã«ã¯ãä»ã®ãã¹ãŠã®ã³ã³ãããŒã©ãŒã§ãããã¯ã©ã¹ã¿ãŒãã¹ã¿ãŒãããããŸãïŒ
gcloud
ããã³kubectl
ã¯APIãšå¯Ÿè©±ããŸãïŒã - ã¯ã©ã¹ã¿ãŒã«ã¯ãå€ãã®ãããŒãã®ã€ã³ã¹ã¿ã³ã¹ã ãæ£ããããã·ã³ãïŒæ£ç¢ºã«ã¯VMã€ã³ã¹ã¿ã³ã¹ïŒããããŸãã
- åã¯ã©ã¹ã¿ãŒã«ã¯ãå°ãªããšã1ã€ã®ãããŒãããŒã«ã ïŒãããã©ã«ãããŒã«ãïŒããããŸããããã¯ãåãæ§æãšåãããã·ã³ã¿ã€ãããæã€ããŒãã€ã³ã¹ã¿ã³ã¹ã®ã³ã¬ã¯ã·ã§ã³ã§ãã
- æåŸã«ãããŒãã®åã€ã³ã¹ã¿ã³ã¹ã¯ãLXCãªã©ã®åçŽãªã³ã³ãããŒã§ãã1ã€ä»¥äžã®ãã³ã³ãããŒããèµ·åããŸãã ãããããªãã®ã¢ããªã±ãŒã·ã§ã³ãæ¬åœã«ããå Žæã§ãã
ã¯ã©ã¹ã¿ãŒã®äœæäŸïŒ
gcloud container clusters create my-web-production \ --enable-cloud-logging \ --enable-cloud-monitoring \ --machine-type n1-standard-4 \ --enable-autoupgrade \ --enable-autoscaling --max-nodes=5 --min-nodes=2 \ --num-nodes 2
åè¿°ã®ããã«ãã¯ã©ã¹ã¿ãŒã¯ãã·ã³ã¿ã€ã n1-standard-4
default-pool
ãäœæãdefault-pool
ã ã¢ããªã±ãŒã·ã§ã³ã«å¿
èŠãªCPU / RAMã®çµã¿åãããéžæããŸãã éžæããã¿ã€ãã«ã¯ã4ã€ã®vCPUãš15 GBã®RAMããããŸãã
ããã©ã«ãã§ã¯ã3ã€ã®ããŒãããéå§ãããããæåã«2ã€ãéžæããŸããããèªåçã«5ã«ã¹ã±ãŒãªã³ã°ãããŸããïŒå¿
èŠã«å¿ããŠåŸã§æŽæ°ã§ããŸãããæåã®æé·ã®äœå°ãããããšã確èªããŠãã ããïŒã ããšãã°ãSidekiqã¯ãŒã«ãŒãéäžçãªããã¯ã°ã©ãŠã³ãåŠçãå®è¡ããããã«ããµã€ãºã®ç°ãªãããŒãã®ã€ã³ã¹ã¿ã³ã¹ã«ããŒã«ãè¿œå ãç¶ããããšãã§ããŸãã 次ã«ãã€ã³ã¹ã¿ã³ã¹ã®ã»ããã«å¯ŸããŠç°ãªããã·ã³ã¿ã€ãã®ããŒãã®å¥åã®ããŒã«ãäœæããŸãã次ã«äŸã瀺ããŸãã
gcloud container node-pools create large-pool \ --cluster=my-web-production \ --node-labels=pool=large \ --machine-type=n1-highcpu-8 \ --num-nodes 1
ãã®ãã1ã€ã®ããŒã«ã¯ã n1-highcpu-8
ã¿ã€ãã®1ã€ã®ããŒããå¶åŸ¡ããŸããããã«ã¯ã7.2 GBã®RAMãåãã8ã€ã®vCPUããããŸãã ããå€ãã®ããã»ããµãããå°ãªãã¡ã¢ãªã highmem
ã«ããŽãªããããããã¯CPUãããå°ãããããå€ãã®ã¡ã¢ãªããããŸãã ç¹°ãè¿ããŸãããããªãã¯ããªããæããã®ãç¥ãå¿
èŠããããŸãã
ããã§éèŠãªç¹ã¯ã-- --node-labels
ã§ãããã¹ãããŒã«éïŒãã®å Žåãããã©ã«ãããŒã«ãšã©ãŒãžããŒã«éïŒãéžæããããã«å±éããããããæ¹æ³ã§ãã
ã¯ã©ã¹ã¿ãŒãäœæãããã次ã®ã³ãã³ããçºè¡ããŠè³æ Œæ
å ±ãååŸããå¿
èŠããããŸãã
gcloud container clusters get-credentials my-web-production
ãã®ã³ãã³ãã¯kubectl
å®çŸ©ãkubectl
ã è€æ°ã®ã¯ã©ã¹ã¿ãŒãããå ŽåïŒ my-web-production
ããã³my-web-staging
ïŒãæ£ããã¯ã©ã¹ã¿ãŒã®get-credentials
泚æããå¿
èŠããããŸããããããªããšãå®çšŒåã¯ã©ã¹ã¿ãŒã§äžéãããã€ã¡ã³ããå®è¡ã§ããŸãã
ããã¯æ··ä¹±ãæããããZSH PROMPTãå€æŽããŠãçŽé¢ããŠããã¯ã©ã¹ã¿ãŒãåžžã«è¡šç€ºããããã«ããŸããã ç§ã¯zsh-kubectl-promptããé©å¿ããŸããïŒ
倧èŠæš¡ãªã¢ããªã±ãŒã·ã§ã³ã«ã¯å€ãã®ã¯ã©ã¹ã¿ãŒãããããããã®ããã³ãããã·ã§ã«ã«è¿œå ããããšã匷ããå§ãããŸãã
ããŒãã€ã³ã¹ã¿ã³ã¹ã®ãããã«ã¢ããªã±ãŒã·ã§ã³ãã©ã®ããã«ãããã€ããŸããïŒ
Dockerã€ã¡ãŒãžãäœæããã«ã¯ãã¢ããªã±ãŒã·ã§ã³ãããžã§ã¯ããªããžããªã«Dockerãã¡ã€ã«ãå¿
èŠã§ãã ããã¯ãRuby on Railsã¢ããªã±ãŒã·ã§ã³ã®äžäŸã§ãã
FROM ruby:2.4.3 ENV RAILS_ENV production ENV SECRET_KEY_BASE xpto RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - RUN apt-get update && apt-get install -y nodejs postgresql-client cron htop vim ADD Gemfile* /app/ WORKDIR /app RUN gem update bundler
Google Cloud Web Consoleã«ã¯ããã©ã€ããŒãDockerã¬ãžã¹ããªã§ãããã³ã³ããã¬ãžã¹ããªãããããŸãã
次ã®ããã«ãããŒã«ã«æ§æã«ãªã¢ãŒãURLãè¿œå ããŸãã
git remote add gcloud https://source.developers.google.com/p/my-project/r/my-app
git push gcloud master
ãã§ããgit push gcloud master
ã ç»åã«ã¿ã°ãä»ããããªã¬ãŒãè¿œå ããããšããå§ãããŸã ã 2ã€ã®ããªã¬ãŒãè¿œå ããŸãã1ã€ã¯latest
ããŒã¯ãä»ãããã1ã€ã¯ã©ã³ãã ãªããŒãžã§ã³çªå·ã§ããŒã¯ãä»ããŸãã åŸã§å¿
èŠã«ãªããŸãã
gitæ§æã§ã¬ãžã¹ããªãªããžããªããªã¢ãŒããšããŠè¿œå ããåŸïŒ git remote add
ïŒããããã¯ãªãã¯ããŸãã ããªã¬ãŒã䜿çšããŠæ§æããé©åãªã¿ã°ã§Dockerã€ã¡ãŒãžã®äœæãéå§ããå¿
èŠããããŸãã
ããŒã¿ããŒã¹æ¥ç¶ãå©çšã§ããªããããRuby on Railsã¢ããªã±ãŒã·ã§ã³ãããŒã¿ããŒã¹æ¥ç¶ãå¿
èŠãšããåæååã«äœããªãããšã確èªããŠãã ããã assets:precompile
-ã¿ã¹ã¯ã誀ã£ãŠã¢ãã«ãåŒã³åºãåæååãããŒããããããActiveRecord :: Base
ããªã¬ãŒãåŒã³åºããŠæ¥ç¶ãè©Šè¡ãããšããäºå®ã«ãããDockerãã«ãã倱æãããšã¹ã¿ãã¯ããå¯èœæ§ããããŸãã
Dockerfileã®Rubyã®ããŒãžã§ã³ãGemfileã®ããŒãžã§ã³ãšäžèŽããŠããããšã確èªããŠãã ãããäžèŽããŠããªãå Žåã倱æããŸãã
å¥åŠãªconfig/application.yml
æ°ã¥ããŸããã ããã¯figaroããã§ãã ã·ã¹ãã å
ã®ENVå€æ°ã®æ§æãç°¡çŽ åããããšããå§ãããŸãã ç§ã¯Railsã®ç§å¯ã奜ãã§ã¯ãããŸãããHerokuãENV varãéåšåããåŸã®å±éã·ã¹ãã ã«ã¯ããŸã銎æã¿ããããŸããã ENVå€æ°ã«åºå·ããŸãã Kubernetesã¯ããã«æè¬ããŸãã
ããã§ãKubernetesããã³yamlãããã€ã¡ã³ããã¡ã€ã«ã®ç°å¢å€æ°ããªãŒããŒã©ã€ãã§ããŸãã ä»ãããäŸãèšå®ãããšãã§ãã deploy / web.yml
ãŸãã¯ãããããªãã«åã£ããã®ãšåŒã¶ããšãã§ããŸãã ãããŠãã¡ããããœãŒã¹ã³ãŒããªããžããªã§ç¢ºèªããŠãã ããã
kind: Deployment apiVersion: apps/v1beta1 metadata: name: web spec: strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 1 minReadySeconds: 10 replicas: 2 template: metadata: labels: app: web spec: containers: - image: gcr.io/my-project/my-app:latest name: my-app imagePullPolicy: Always ports: - containerPort: 4001 command: ["passenger", "start", "-p", "4001", "-e", "production", "--max-pool-size", "2", "--min-instances", "2", "--no-friendly-error-pages" "--max-request-queue-time", "10", "--max-request-time", "10", "--pool-idle-time", "0", "--memory-limit", "300"] env: - name: "RAILS_LOG_TO_STDOUT" value: "true" - name: "RAILS_ENV" value: "production" # ... obviously reduced the many ENV vars for brevity - name: "REDIS_URL" valueFrom: secretKeyRef: name: my-env key: REDIS_URL - name: "SMTP_USERNAME" valueFrom: secretKeyRef: name: my-env key: SMTP_USERNAME - name: "SMTP_PASSWORD" valueFrom: secretKeyRef: name: my-env key: SMTP_PASSWORD # ... this part below is mandatory for Cloud SQL - name: DB_HOST value: 127.0.0.1 - name: DB_PASSWORD valueFrom: secretKeyRef: name: cloudsql-db-credentials key: password - name: DB_USER valueFrom: secretKeyRef: name: cloudsql-db-credentials key: username - image: gcr.io/cloudsql-docker/gce-proxy:latest name: cloudsql-proxy command: ["/cloud_sql_proxy", "--dir=/cloudsql", "-instances=my-project:us-west1:my-db=tcp:5432", "-credential_file=/secrets/cloudsql/credentials.json"] volumeMounts: - name: cloudsql-instance-credentials mountPath: /secrets/cloudsql readOnly: true - name: ssl-certs mountPath: /etc/ssl/certs - name: cloudsql mountPath: /cloudsql volumes: - name: cloudsql-instance-credentials secret: secretName: cloudsql-instance-credentials - name: ssl-certs hostPath: path: /etc/ssl/certs - name: cloudsql emptyDir:
äŸã«ã€ããŠèª¬æããŸãã
kind
ãšapiVersion
ã¯éèŠã§ããããã¥ã¡ã³ãã«æ³šæããŠãã ãããå€æŽãããå¯èœæ§ããããŸãã ããã¯DeploymentãšåŒã°ãããã®ã§ãã 以åã¯ã¬ããªã±ãŒã·ã§ã³ã³ã³ãããŒã©ãŒããããŸããïŒå€ããã¥ãŒããªã¢ã«ã«ãããŸãïŒãããã䜿çšãããŠããŸããã æšå¥šäºé
ïŒ ReplicaSetã䜿çšããŠãã ããã- ã¹ããŒããã¹ããŒããšåŒã³
web
ã metadata:name
with web
ãŸãã spec:template:metadata:labels
ã«æ³šæããŠspec:template:metadata:labels
ããã§ãåãããã¯ãlabel app: web
ãŸãã åŸã§ããµãŒãã¹ãã»ã¯ã·ã§ã³ã§ã¢ã€ãã ãéžæã§ããããã«ããå¿
èŠããããŸãã - ç§ã«ã¯ãããŒãªã³ã°æŽæ°ãæ§æãã
spec:strategy
ããããŸãã spec:replicas
ã¯ãå¿
èŠãªããŒã¹æ°ãéç¥ããŸãã ãã¹ãããŒã«ã®ãã·ã³ã¿ã€ããæåã§èšç®ããåã¢ããªã±ãŒã·ã§ã³ã®ãµãŒããŒãªãœãŒã¹ãå
±æããå¿
èŠããããŸãã- ãlastãã¿ã°ã§äœæããDockerã€ã¡ãŒãžã
spec: template: spec: container: image
ãŸãã - æ¬çªæ§æã§Passengerã䜿çšããŠããŸãïŒ Phusionã®ããã¥ã¡ã³ããã芧ãã ããïŒ
- specïŒtemplateïŒspecïŒcontainerïŒenvã»ã¯ã·ã§ã³ã§ã¯ãVAR ENVãå®éã®è£œé ã®ç§å¯ã§ãªãŒããŒã©ã€ãã§ããŸãã å€ããšã³ã³ãŒããããããã®ããã€ã¹ã䜿çšã§ããŸãã
- name: "SMTP_USERNAME" valueFrom: secretKeyRef: name: my-env key: SMTP_USERNAME
ããã¯ãmy-envãšããååã®ãç§å¯ããªããžããªãžã®ãªã³ã¯ã§ãã ãããŠãããã¯ããªããããªãèªèº«ãäœæããæ¹æ³ã§ãïŒ
kubectl create secret generic my-env \ --from-literal=REDIS_URL=redis:
ã³ãã³ãã©ã€ã³ãããã¹ãŠã宣èšããã®ã§ã¯ãªããããã¹ããã¡ã€ã«ãããŠã³ããŒãã§ãããããããã¥ã¡ã³ãããèªã¿ãã ããã
å
ã»ã©èšã£ãããã«ãããŒã¿ããŒã¹ã«ã¯ãããŒãžããµãŒãã¹ã䜿çšããããšæããŸãã Dockerã€ã¡ãŒãžãã¢ããããŒãã§ããŸããããå§ãããŸããã åãããšã¯ãRedisãMongoãªã©ã®ããŒã¿ããŒã¹ãªã©ã®ä»ã®ãµãŒãã¹ã«ãåœãŠã¯ãŸããŸãã AWSã䜿çšããå Žåã Google Cloud SQLã¯RDSã«äŒŒãŠããããšã«æ³šæããŠãã ããã
PostgreSQLã®ã€ã³ã¹ã¿ã³ã¹ãäœæããåŸãWebã¢ããªã±ãŒã·ã§ã³ããçŽæ¥ã¢ã¯ã»ã¹ããããšã¯ã§ããŸããã 2çªç®ã®Dockerã€ã¡ãŒãžãCloudSQL Proxyãã®ãã³ãã¬ãŒãããããŸãã
ãããè¡ãã«ã¯ãæåã«ãµãŒãã¹ã¢ã«ãŠã³ããäœæããå¿
èŠããããŸãã
gcloud sql users create proxyuser host
PostgreSQLã€ã³ã¹ã¿ã³ã¹ãäœæããåŸãJSONè³æ Œæ
å ±ãããŒãããããã«æ±ããããŸãã ã©ããã«ä¿åããŸãã 匷åãªãã¹ã¯ãŒããå¿
èŠã§ããããšãæãåºããŠã¯ãããŸããã è¿œå ã®ç§å¯ãäœæããå¿
èŠããããŸãã
kubectl create secret generic cloudsql-instance-credentials \ --from-file=credentials.json=/home/myself/downloads/my-db-12345.json kubectl create secret generic cloudsql-db-credentials \ --from-literal=username=proxyuser --from-literal=password=abcd1234
ãããã¯ãå±éã®ãã®éšåã§èšåãããŠããŸãã
- image: gcr.io/cloudsql-docker/gce-proxy:latest name: cloudsql-proxy command: ["/cloud_sql_proxy", "--dir=/cloudsql", "-instances=my-project:us-west1:my-db=tcp:5432", "-credential_file=/secrets/cloudsql/credentials.json"] volumeMounts: - name: cloudsql-instance-credentials mountPath: /secrets/cloudsql readOnly: true - name: ssl-certs mountPath: /etc/ssl/certs - name: cloudsql mountPath: /cloudsql volumes: - name: cloudsql-instance-credentials secret: secretName: cloudsql-instance-credentials - name: ssl-certs hostPath: path: /etc/ssl/certs - name: cloudsql emptyDir:
ããŒã¿ããŒã¹åïŒãã®å Žåã¯my-dbïŒãã³ãã³ãã®-instanceã«è¿œå ããå¿
èŠããããŸãã
ã¡ãªã¿ã«ã gce-proxy:latest
ã¯ãããŒãžã§ã³1.11ãæ¢ã«ååšããå Žåã«ããŒãžã§ã³1.09ãæããŸãã æ°ããããŒãžã§ã³ã§ã¯ãæ¥ç¶ãåæãããåŸ
ã¡æéãé·ããªããšããé çã®çš®ãäœæãããŸããã ãããã£ãŠãç§ã¯æ°ããããŒãžã§ã³-1.09ã«æ»ãããã¹ãŠãããŸããããŸããã ã ããããã¹ãŠãæ°ããããã§ã¯ãããŸããã ã€ã³ãã©ã¹ãã©ã¯ãã£ã§ã¯ãå®å®æ§ãå³å®ããæ¹ãé©åã§ãã
ãŸãããããã1ã€ã®ãããã·ã®ã¿ã«æ¥ç¶ã§ããããã«ãåãããã«åå¥ã®CloudSQLã€ã³ã¹ã¿ã³ã¹ãããŒãããã®ã§ã¯ãªããåå¥ã®CloudSQLã€ã³ã¹ã¿ã³ã¹ãããŒããããªãã·ã§ã³ãå¿
èŠã«ãªãå ŽåããããŸãã ãã®ã¹ã¬ãããããŒãã«ã€ããŠèªãã§ãã ããã
ãµãã«ãŒãã³ã1ã€ã®ãããã·ã®ã¿ã«æ¥ç¶ã§ããããã«ããµãããšã«CloudSQLã®ã€ã³ã¹ã¿ã³ã¹ãçšæãã代ããã«ãCloudSQLã®åå¥ã®ã€ã³ã¹ã¿ã³ã¹ãããŠã³ããŒãã§ããŸãã ãã®èšäºãèªãããšããå§ãããŸã ã
äœã圱é¿ãåããŠããªãããã§ãã ãããã£ãŠã ããŒãããŒããµãŒãã¹ãä»ããŠããããå
¬éããå¿
èŠããããŸãã deploy/web-svc.yamlfile
äœæããŸãããã
apiVersion: v1 kind: Service metadata: name: web-svc spec: sessionAffinity: None ports: - port: 80 targetPort: 4001 protocol: TCP type: NodePort selector: app: web
ãããspec:template:metadata:labels
ã®éèŠæ§ã匷調ããçç±ã§ãã spec:selector
ã§äœ¿çšããŠãæ£ããã³ã³ãããéžæããŸãã
ãããã®2ã€ã®ãããã次ã®ããã«æ¡åŒµã§ããŸãã
kubectl create -f deploy/web.yml kubectl create -f deploy/web-svc.yml
ããããkubectl get pods --watch
ã䜿çšããŠäœæãããŠkubectl get pods --watch
ãŸãã
è² è·åæ£
å€ãã®æç§æžã§ã¯ãããŒã¹ã¯Load BalancerãšåŒã°ããå¥ã®ãµãŒãã¹ãéããŠæäŸãããŸãã 圌ãå§åäžã§ã©ã®ããã«æ¯ãèãããSSLçµäºããããã©ãããªã©ã¯ããããŸãããNGINXã³ã³ãããŒã©ãŒã䜿çšããŠIngress Load Balancerããã«ã«ãªã³ã«ããããšã«ããŸããã
ãŸã第äžã«ãç§ã¯ããã®ããã«å¥ã®ããŒãããŒã«ãäœæããããšã«ããŸãããäŸãã°ïŒ
gcloud container node-pools create web-load-balancer \ --cluster=my-web-production \ --node-labels=role=load-balancer \ --machine-type=g1-small \ --num-nodes 1 \ --max-nodes 3 --min-nodes=1 \ --enable-autoscaling
large-pool
äŸãäœæããããã large-pool
--node-labels
ãè¿œå ããŠdefault-pool
代ããã«ã³ã³ãããŒã©ãŒãèšå®ãdefault-pool
ã ããŒãã€ã³ã¹ã¿ã³ã¹ã®ååãç¥ãå¿
èŠãããã次ã®ããã«ãããè¡ãããšãã§ããŸãã
$ gcloud compute instances list NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS gke-my-web-production-default-pool-123-123 us-west1-a n1-standard-4 10.128.0.1 123.123.123.12 RUNNING gke-my-web-production-large-pool-123-123 us-west1-a n1-highcpu-8 10.128.0.2 50.50.50.50 RUNNING gke-my-web-production-web-load-balancer-123-123 us-west1-a g1-small 10.128.0.3 70.70.70.70 RUNNING
ä¿åããŠãã ããïŒ
export LB_INSTANCE_NAME=gke-my-web-production-web-load-balancer-123-123
å€éšIPã¢ãã¬ã¹ãæåã§äºçŽããååãä»ããããšãã§ããŸãã
gcloud compute addresses create ip-web-production \
äºçŽæžã¿ã®IPã¢ãã¬ã¹ã111.111.111.111ããçæãããšããŸãã ä¿åããŠãã ããïŒ
export LB_ADDRESS_IP=$(gcloud compute addresses list | grep "ip-web-production" | awk '{print $3}')
ã¢ãã¬ã¹ãè² è·åæ£ããŒãã®ã€ã³ã¹ã¿ã³ã¹ã«é¢é£ä»ããŸãã
export LB_INSTANCE_NAT=$(gcloud compute instances describe $LB_INSTANCE_NAME | grep -A3 networkInterfaces: | tail -n1 | awk -F': ' '{print $2}') gcloud compute instances delete-access-config $LB_INSTANCE_NAME \ --access-config-name "$LB_INSTANCE_NAT" gcloud compute instances add-access-config $LB_INSTANCE_NAME \ --access-config-name "$LB_INSTANCE_NAT" --address $LB_ADDRESS_IP
æ®ãã®Ingress Deploymentæ§æãè¿œå ããŸãã ããã«ã¯å€ãã®æéãããããŸãããã»ãšãã©ã¯ãã¿ãŒã³ã«åŸããŸãã default-http-backend
ãšããå¥ã®Webã¢ããªã±ãŒã·ã§ã³ãå®çŸ©ããããšããå§ããŸãããã äœããã®çç±ã§Webã³ã³ãããå©çšã§ããªãå ŽåãHTTPãªã¯ãšã¹ãã«å¿çããããã«äœ¿çšãããŸãã ãããdeploy / default-web.yml
ãšåŒã³ãŸãããïŒ
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: default-http-backend spec: replicas: 1 template: metadata: labels: app: default-http-backend spec: terminationGracePeriodSeconds: 60 containers: - name: default-http-backend # Any image is permissable as long as: # 1. It serves a 404 page at / # 2. It serves 200 on a /healthz endpoint image: gcr.io/google_containers/defaultbackend:1.0 livenessProbe: httpGet: path: /healthz port: 8080 scheme: HTTP initialDelaySeconds: 30 timeoutSeconds: 5 ports: - containerPort: 8080 resources: limits: cpu: 10m memory: 20Mi requests: cpu: 10m memory: 20Mi
äœãå€æŽããå¿
èŠã¯ãããŸããã ããã§ãå±éãã¿ãŒã³ã«ç²ŸéããŸããã NodePortãä»ããŠãã³ãã¬ãŒããå
¬éããå¿
èŠãããããã deploy/default-web-svc.yml
è¿œå ããŸãããã
kind: Service apiVersion: v1 metadata: name: default-http-backend spec: selector: app: default-http-backend ports: - protocol: TCP port: 80 targetPort: 8080 type: NodePort
ç¹°ãè¿ããŸãããäœãå€æŽããªãã§ãã ããã 次ã®3ã€ã®ãã¡ã€ã«ã¯éèŠãªéšåã§ãã ãŸããNGINXããŒããã©ã³ãµãŒãäœæãã deploy / nginx.yml
ãŸãã
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx-ingress-controller spec: replicas: 1 template: metadata: labels: k8s-app: nginx-ingress-lb spec: # hostNetwork makes it possible to use ipv6 and to preserve the source IP correctly regardless of docker configuration # however, it is not a hard dependency of the nginx-ingress-controller itself and it may cause issues if port 10254 already is taken on the host # that said, since hostPort is broken on CNI (https://github.com/kubernetes/kubernetes/issues/31307) we have to use hostNetwork where CNI is used hostNetwork: true terminationGracePeriodSeconds: 60 nodeSelector: role: load-balancer containers: - args: - /nginx-ingress-controller - "--default-backend-service=$(POD_NAMESPACE)/default-http-backend" - "--default-ssl-certificate=$(POD_NAMESPACE)/cloudflare-secret" env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: "gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.5" imagePullPolicy: Always livenessProbe: httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 timeoutSeconds: 5 name: nginx-ingress-controller ports: - containerPort: 80 name: http protocol: TCP - containerPort: 443 name: https protocol: TCP volumeMounts: - mountPath: /etc/nginx-ssl/dhparam name: tls-dhparam-vol volumes: - name: tls-dhparam-vol secret: secretName: tls-dhparam
nodeSelector
ã¯ãæ°ããããŒãããŒã«ãäœæãããšãã«è¿œå ããããŒãã©ãã«ãäœæããããšã«æ³šæããŠnodeSelector
ã
ã¿ã°ãã¬ããªã«ã®æ°ã䜿çšãããå ŽåããããŸãã ããã«ãç§ãtls-dhparam-vol
ãšåŒãã ããªã¥ãŒã ãããŠã³ããããŠããããšã«æ³šæããããšãéèŠã§ãã ããã¯Diffie Hellman Ephemeral Parameters
ã§ãã çæããŸãïŒ
sudo openssl dhparam -out ~/documents/dhparam.pem 2048 kubectl create secret generic tls-dhparam --from-file=/home/myself/documents/dhparam.pem kubectl create secret generic tls-dhparam --from-file=/home/myself/documents/dhparam.pem
ã³ã³ãããŒã©ã€ã¡ãŒãžã«ããŒãžã§ã³0.9.0-beta_5ã䜿çšããŠããããšã«æ³šæããŠãã ããã ä»ã®ãšããåé¡ãªãåäœããŸãã ãã ãããªãªãŒã¹ããŒããæ°ããããŒãžã§ã³ã«æ³šæããŠãç¬èªã®ãã¹ããè¡ã£ãŠãã ããã
ç¹°ãè¿ããŸãããè² è·åæ£ãµãŒãã¹ãä»ããŠãã®Ingressã³ã³ãããŒã©ãŒãå
¬éããŸãããã deploy / nginx-svc.yml
ãšåŒã³ãŸãããïŒ
apiVersion: v1 kind: Service metadata: name: nginx-ingress spec: type: LoadBalancer loadBalancerIP: 111.111.111.111 ports: - name: http port: 80 targetPort: http - name: https port: 443 targetPort: https selector: k8s-app: nginx-ingress-lb
äžèšã§äºçŽãã LB_INGRESS_IP ENV var
ä¿åããéçå€éšIPãèŠããŠããŸããïŒ ãããspec: loadBalancerIP
ã«å«ããå¿
èŠããããŸãspec: loadBalancerIP
ã»ã¯ã·ã§ã³ããã¯ãDNSãµãŒãã¹ã«ãã¬ã³ãŒãããšããŠè¿œå ããIPã¢ãã¬ã¹ã§ããããŸãïŒwww.my-app.com.brãCloudFlareã«ãããã³ã°ãããšããŸãããïŒã
ç¬èªã®Ingressèšå®ãäœæã§ããããã«ãªããŸããã次ã®ããã«deploy / ingress.yml
ãäœæããŸãããã
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress annotations: kubernetes.io/ingress.class: "nginx" nginx.org/ssl-services: "web-svc" kubernetes.io/ingress.global-static-ip-name: ip-web-production ingress.kubernetes.io/ssl-redirect: "true" ingress.kubernetes.io/rewrite-target: / spec: tls: - hosts: - www.my-app.com.br secretName: cloudflare-secret rules: - host: www.my-app.com.br http: paths: - path: / backend: serviceName: web-svc servicePort: 80
ãããã£ãŠãWebã¢ãžã¥ãŒã«çšã«äœæãããNodePortãµãŒãã¹ãnginxãã°ã€ã³ã³ã³ãããŒã©ãŒã«æ¥ç¶ãã spec: tls: secretName
ä»ããŠSSLè£å®ãè¿œå ããŸããã äœææ¹æ³ã¯ïŒ ãŸããäŸãšããŠCloudFlareã䜿çšããŠSSL蚌ææžãååŸããå¿
èŠããããŸãã
賌å
¥æã«ããããã€ããŒã¯ããŠã³ããŒãçšã®ç§å¯ãã¡ã€ã«ãæäŸããå¿
èŠããããŸãïŒå®å
šã«ä¿ç®¡ããŠãã ããïŒDropboxã®ãããªãã¯ãã©ã«ããŒã¯å®å
šã§ã¯ãããŸããïŒïŒã 次ã«ã次ã®ããã«ã€ã³ãã©ã¹ãã©ã¯ãã£ã«è¿œå ããå¿
èŠããããŸãã
kubectl create secret tls cloudflare-secret \
å€ãã®ãã¡ã€ã«ãç·šéããã®ã§ãããŒããã©ã³ã·ã³ã°ããã±ãŒãžå
šäœããããã€ã§ããŸãã
kubectl create -f deploy/default-web.yml kubectl create -f deploy/default-web-svc.yml kubectl create -f deploy/nginx.yml kubectl create -f deploy/nginx-svc.yml kubectl create -f deploy/ingress.yml
ãã®NGINX Ingressèšå®ã¯ã Zihao Zhangã®ããã°æçš¿ã«åºã¥ããŠããŸãã Kubernetã€ã³ãã¥ããŒã¿ãŒã®ãªããžããªã«ãäŸããããŸã ã ããªãã¯ããããã§ãã¯ã¢ãŠãã§ããŸãã
ãã¹ãŠæ£ããè¡ã£ãå Žåã httpsïŒ//www.my-app-com.brã§Webã¢ããªã±ãŒã·ã§ã³ãããŠã³ããŒããããŸãã 次ã®ããã«ãCloudFlareãä»ããŠæåã®ãã€ãæéïŒTTFBïŒã確èªã§ããŸãã
curl -vso /dev/null -w "Connect: %{time_connect} \n TTFB: %{time_starttransfer} \n Total time: %{time_total} \n" https://www.my-app.com.br
TTFBãé
ãå ŽåïŒ
curl --resolve www.my-app.com.br:443:111.111.111.111 https://www.my-app.com.br -svo /dev/null -k -w "Connect: %{time_connect} \n TTFB: %{time_starttransfer} \n Total time: %{time_total} \n"
TTFBã¯çŽ1ç§ä»¥äžã«ããå¿
èŠããããŸãã ãã以å€ã®å Žåãã¢ããªã±ãŒã·ã§ã³ã«ãšã©ãŒãããããšãæå³ããŸãã ãã·ã³ããŒãã€ã³ã¹ã¿ã³ã¹ã®ã¿ã€ãã1ã€ã®ã¢ãžã¥ãŒã«ã«ããŒããããŠããã¯ãŒã«ãŒã®æ°ãCloudSQLãããã·ããŒãžã§ã³ãNGINXã³ã³ãããŒã©ãŒããŒãžã§ã³ãªã©ã確èªããå¿
èŠããããŸããããã¯è©Šè¡é¯èª€ã®æé ã§ãã æŽå¯ã®ããã«ããŒããŒãŸãã¯WebããŒãžãã¹ãã«ãµã€ã³ã¢ããããŸãã
ããŒãªã³ã°æŽæ°
ãã¹ãŠãæ©èœããããã«ãªã£ãã®ã§ãåé ã§è¿°ã¹ãããŒãªã³ã°ã¢ããããŒããæŽæ°ããã«ã¯ã©ãããã°ããã§ããïŒ æåã«ã³ã³ããã¬ãžã¹ããªãªããžããªã§git push
ãå®è¡ããDockerã€ã¡ãŒãžãäœæãããã®ãåŸ
ã¡ãŸãã
èŠããŠãããŠãããªã¬ãŒã«ã©ã³ãã ãªããŒãžã§ã³çªå·ã®ç»åãé
眮ãããŸãããïŒ ããã䜿ã£ãŠã¿ãŸãããïŒGoogle Cloudã³ã³ãœãŒã«ã®Container Registryã®Build Historyãªã¹ãã§èŠãããšãã§ããŸãïŒïŒ
kubectl set image deployment web my-app=gcr.io/my-project/my-app:1238471234g123f534f543541gf5
deploy/web.yml
宣èšãããŠããã®ãšåãååãšã€ã¡ãŒãžã䜿çšããå¿
èŠããããŸãã ããŒãªã³ã°æŽæ°ãéå§ãããæ°ããã¢ãžã¥ãŒã«ãè¿œå ãããŠããããããã¯ãå®äºããŸãããã¹ãŠã®ãŠãŒã¶ãŒãããŠã³ã¿ã€ã ãªãã§æŽæ°ããããŸã§ããããã¯å®äºããŸãã
ããŒãªã³ã°æŽæ°ã¯æ
éã«å®è¡ããå¿
èŠããããŸãã ããšãã°ãå±éã«ããŒã¿ããŒã¹ã®ç§»è¡ãå¿
èŠãªå Žåã¯ãã¡ã³ããã³ã¹ãŠã£ã³ããŠãè¿œå ããå¿
èŠããããŸãïŒãã©ãã£ãã¯ãå°ãªãæ·±å€ã«è¡ãå¿
èŠããããŸãïŒã ãããã£ãŠã移è¡ã³ãã³ãã¯æ¬¡ã®ããã«å®è¡ã§ããŸãã
kubectl get pods # to get a pod name kubectl exec -it my-web-12324-121312 /app/bin/rails db:migrate # you can also bash to a pod like this, but remember that this is an ephemeral container, so file you edit and write there disappear on the next restart: kubectl exec -it my-web-12324-121312 bash
, -, :
kubectl delete -f deploy/web.yml && kubectl apply -f deploy/web.yml
:
« » â / . Google Cloud . , . API .
SSD- :
gcloud compute disks create
. , gke-my-web-app-default-pool-123-123
. my-data
:
gcloud compute instances attach-disk gke-my-web-app-default-pool-123-123 --disk my-data --device-name my-data gcloud compute ssh gke-my-web-app-default-pool-123-123
ssh . sudo lsblk
, 500 , , / dev / sdb
. , , !
sudo mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/sdb
SSH :
gcloud compute instances detach-disk gke-my-web-app-default-pool-123-123
, yaml :
spec: containers: - image: ... name: my-app volumeMounts: - name: my-data mountPath: /data # readOnly: true # ... volumes: - name: my-data gcePersistentDisk: pdName: my-data fsType: ext4
CronJob deploy / auto-snapshot.yml
:
apiVersion: batch/v1beta1 kind: CronJob metadata: name: auto-snapshot spec: schedule: "0 4 * * *" concurrencyPolicy: Forbid jobTemplate: spec: template: spec: restartPolicy: OnFailure containers: - name: auto-snapshot image: grugnog/google-cloud-auto-snapshot command: ["/opt/entrypoint.sh"] env: - name: "GOOGLE_CLOUD_PROJECT" value: "my-project" - name: "GOOGLE_APPLICATION_CREDENTIALS" value: "/credential/credential.json" volumeMounts: - mountPath: /credential name: editor-credential volumes: - name: editor-credential secret: secretName: editor-credential
, IAM & admin Google Cloud, JSON , , :
kubectl create secret generic editor-credential \
: cron. «0 4 *» , 4 .
.
, , . Kubernetes, Deployment, Service, Ingress, ReplicaSet, DaemonSet .
, multi-region High Availability, .
: My Notes about a Production-grade Ruby on Rails Deployment on Google Cloud Kubernetes Engine