resolve conflict
|
@ -5,7 +5,7 @@ charset = utf-8
|
|||
max_line_length = 80
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{html,js,json,sass,md,mmark,toml,yaml}]
|
||||
[*.{css,html,js,json,sass,md,mmark,toml,yaml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
your pull request. The description should explain what will change,
|
||||
and why.
|
||||
|
||||
PLEASE title the FIRST commit appropriately, so that if you squash all
|
||||
your commits into one, the combined commit message makes sense.
|
||||
For overall help on editing and submitting pull requests, visit:
|
||||
https://kubernetes.io/docs/contribute/start/#improve-existing-content
|
||||
|
||||
|
@ -14,7 +16,7 @@
|
|||
|
||||
If you're working on a different localization (not English), or you
|
||||
are documenting a feature that will be part of a future release, see
|
||||
https://kubernetes.io/docs/contribute/start#choose-which-git-branch-to-use
|
||||
https://kubernetes.io/docs/contribute/new-content/overview/#choose-which-git-branch-to-use
|
||||
for advice.
|
||||
|
||||
-->
|
||||
|
|
|
@ -33,4 +33,4 @@ resources/
|
|||
# Netlify Functions build output
|
||||
package-lock.json
|
||||
functions/
|
||||
node_modules/
|
||||
node_modules/
|
|
@ -0,0 +1,16 @@
|
|||
DirectoryPath: public/docs
|
||||
IgnoreDirectoryMissingTrailingSlash: true
|
||||
CheckExternal: false
|
||||
IgnoreAltMissing: true
|
||||
CheckImages: false
|
||||
CheckScripts: false
|
||||
CheckMeta: false
|
||||
CheckMetaRefresh: false
|
||||
CheckLinks: false
|
||||
EnforceHTML5: false
|
||||
EnforceHTTPS: false
|
||||
IgnoreDirectoryMissingTrailingSlash: false
|
||||
IgnoreInternalEmptyHash: true
|
||||
IgnoreEmptyHref: true
|
||||
IgnoreDirs:
|
||||
- "reference/generated/kubernetes-api"
|
53
Makefile
|
@ -1,9 +1,16 @@
|
|||
DOCKER = docker
|
||||
HUGO_VERSION = $(shell grep ^HUGO_VERSION netlify.toml | tail -n 1 | cut -d '=' -f 2 | tr -d " \"\n")
|
||||
DOCKER_IMAGE = kubernetes-hugo
|
||||
DOCKER_RUN = $(DOCKER) run --rm --interactive --tty --volume $(CURDIR):/src
|
||||
NODE_BIN = node_modules/.bin
|
||||
NETLIFY_FUNC = $(NODE_BIN)/netlify-lambda
|
||||
HUGO_VERSION = $(shell grep ^HUGO_VERSION netlify.toml | tail -n 1 | cut -d '=' -f 2 | tr -d " \"\n")
|
||||
NODE_BIN = node_modules/.bin
|
||||
NETLIFY_FUNC = $(NODE_BIN)/netlify-lambda
|
||||
|
||||
# The CONTAINER_ENGINE variable is used for specifying the container engine. By default 'docker' is used
|
||||
# but this can be overridden when calling make, e.g.
|
||||
# CONTAINER_ENGINE=podman make container-image
|
||||
CONTAINER_ENGINE ?= docker
|
||||
CONTAINER_IMAGE = kubernetes-hugo
|
||||
CONTAINER_RUN = $(CONTAINER_ENGINE) run --rm --interactive --tty --volume $(CURDIR):/src
|
||||
|
||||
CCRED=\033[0;31m
|
||||
CCEND=\033[0m
|
||||
|
||||
.PHONY: all build build-preview help serve
|
||||
|
||||
|
@ -36,14 +43,42 @@ serve: ## Boot the development server.
|
|||
hugo server --buildFuture
|
||||
|
||||
docker-image:
|
||||
$(DOCKER) build . --tag $(DOCKER_IMAGE) --build-arg HUGO_VERSION=$(HUGO_VERSION)
|
||||
@echo -e "$(CCRED)**** The use of docker-image is deprecated. Use container-image instead. ****$(CCEND)"
|
||||
$(MAKE) container-image
|
||||
|
||||
docker-build:
|
||||
$(DOCKER_RUN) $(DOCKER_IMAGE) hugo
|
||||
@echo -e "$(CCRED)**** The use of docker-build is deprecated. Use container-build instead. ****$(CCEND)"
|
||||
$(MAKE) container-build
|
||||
|
||||
docker-serve:
|
||||
$(DOCKER_RUN) -p 1313:1313 $(DOCKER_IMAGE) hugo server --buildFuture --bind 0.0.0.0
|
||||
@echo -e "$(CCRED)**** The use of docker-serve is deprecated. Use container-serve instead. ****$(CCEND)"
|
||||
$(MAKE) container-serve
|
||||
|
||||
container-image:
|
||||
$(CONTAINER_ENGINE) build . \
|
||||
--network=host \
|
||||
--tag $(CONTAINER_IMAGE) \
|
||||
--build-arg HUGO_VERSION=$(HUGO_VERSION)
|
||||
|
||||
container-build:
|
||||
$(CONTAINER_RUN) $(CONTAINER_IMAGE) hugo
|
||||
|
||||
container-serve:
|
||||
$(CONTAINER_RUN) --mount type=tmpfs,destination=/src/resources,tmpfs-mode=0755 -p 1313:1313 $(CONTAINER_IMAGE) hugo server --buildFuture --bind 0.0.0.0
|
||||
|
||||
test-examples:
|
||||
scripts/test_examples.sh install
|
||||
scripts/test_examples.sh run
|
||||
|
||||
.PHONY: link-checker-setup
|
||||
link-checker-image-pull:
|
||||
$(CONTAINER_ENGINE) pull wjdp/htmltest
|
||||
|
||||
docker-internal-linkcheck:
|
||||
@echo -e "$(CCRED)**** The use of docker-internal-linkcheck is deprecated. Use container-internal-linkcheck instead. ****$(CCEND)"
|
||||
$(MAKE) container-internal-linkcheck
|
||||
|
||||
container-internal-linkcheck: link-checker-image-pull
|
||||
$(CONTAINER_RUN) $(CONTAINER_IMAGE) hugo --config config.toml,linkcheck-config.toml --buildFuture
|
||||
$(CONTAINER_ENGINE) run --mount type=bind,source=$(CURDIR),target=/test --rm wjdp/htmltest htmltest
|
||||
|
||||
|
|
6
OWNERS
|
@ -7,10 +7,10 @@ approvers:
|
|||
- sig-docs-en-owners # Defined in OWNERS_ALIASES
|
||||
|
||||
emeritus_approvers:
|
||||
- chenopis
|
||||
- jaredbhatti
|
||||
# chenopis, you're welcome to return when you're ready to resume PR wrangling
|
||||
# jaredbhatti, you're welcome to return when you're ready to resume PR wrangling
|
||||
# stewart-yu, you're welcome to return when you're ready to resume PR wrangling
|
||||
- stewart-yu
|
||||
|
||||
labels:
|
||||
- sig/docs
|
||||
- sig/docs
|
||||
|
|
|
@ -41,13 +41,13 @@ aliases:
|
|||
sig-docs-en-owners: # Admins for English content
|
||||
- bradtopol
|
||||
- daminisatya
|
||||
- jaredbhatti
|
||||
- jimangel
|
||||
- kbarnard10
|
||||
- kbhawkey
|
||||
- makoscafee
|
||||
- onlydole
|
||||
- Rajakavitha1
|
||||
- savitharaghunathan
|
||||
- sftim
|
||||
- steveperry-53
|
||||
- tengqm
|
||||
|
@ -58,7 +58,6 @@ aliases:
|
|||
sig-docs-en-reviews: # PR reviews for English content
|
||||
- bradtopol
|
||||
- daminisatya
|
||||
- jaredbhatti
|
||||
- jimangel
|
||||
- kbarnard10
|
||||
- kbhawkey
|
||||
|
@ -124,6 +123,8 @@ aliases:
|
|||
sig-docs-id-reviews: # PR reviews for Indonesian content
|
||||
- girikuncoro
|
||||
- irvifa
|
||||
- wahyuoi
|
||||
- phanama
|
||||
sig-docs-it-owners: # Admins for Italian content
|
||||
- fabriziopandini
|
||||
- mattiaperi
|
||||
|
@ -133,14 +134,15 @@ aliases:
|
|||
- mattiaperi
|
||||
- micheleberardi
|
||||
sig-docs-ja-owners: # Admins for Japanese content
|
||||
- cstoku
|
||||
# cstoku
|
||||
- inductor
|
||||
- nasa9084
|
||||
sig-docs-ja-reviews: # PR reviews for Japanese content
|
||||
- cstoku
|
||||
- bells17
|
||||
# cstoku
|
||||
- inductor
|
||||
- makocchi-git
|
||||
- MasayaAoyama
|
||||
# MasayaAoyama
|
||||
- nasa9084
|
||||
- oke-py
|
||||
sig-docs-ko-owners: # Admins for Korean content
|
||||
|
@ -148,6 +150,7 @@ aliases:
|
|||
- gochist
|
||||
- ianychoi
|
||||
- seokho-son
|
||||
- ysyukr
|
||||
- zacharysarah
|
||||
sig-docs-ko-reviews: # PR reviews for Korean content
|
||||
- ClaudiaJKang
|
||||
|
@ -155,13 +158,13 @@ aliases:
|
|||
- ianychoi
|
||||
- seokho-son
|
||||
- ysyukr
|
||||
sig-docs-maintainers: # Website maintainers
|
||||
sig-docs-leads: # Website chairs and tech leads
|
||||
- jimangel
|
||||
- kbarnard10
|
||||
- pwittrock
|
||||
- steveperry-53
|
||||
- kbhawkey
|
||||
- onlydole
|
||||
- sftim
|
||||
- zacharysarah
|
||||
- zparnold
|
||||
sig-docs-zh-owners: # Admins for Chinese content
|
||||
- chenopis
|
||||
- chenrui333
|
||||
|
@ -169,7 +172,6 @@ aliases:
|
|||
- haibinxie
|
||||
- hanjiayao
|
||||
- lichuqiang
|
||||
- markthink
|
||||
- SataQiu
|
||||
- tengqm
|
||||
- xiangpengzhao
|
||||
|
@ -179,8 +181,8 @@ aliases:
|
|||
sig-docs-zh-reviews: # PR reviews for Chinese content
|
||||
- chenrui333
|
||||
- idealhack
|
||||
- markthink
|
||||
- SataQiu
|
||||
- tanjunchen
|
||||
- tengqm
|
||||
- xiangpengzhao
|
||||
- xichengliudui
|
||||
|
@ -221,3 +223,14 @@ aliases:
|
|||
- mfilocha
|
||||
- nvtkaszpir
|
||||
- kpucynski
|
||||
sig-docs-uk-owners: # Admins for Ukrainian content
|
||||
- anastyakulyk
|
||||
- butuzov
|
||||
- MaxymVlasov
|
||||
sig-docs-uk-reviews: # PR reviews for Ukrainian content
|
||||
- anastyakulyk
|
||||
- Arhell
|
||||
- butuzov
|
||||
- idvoretskyi
|
||||
- MaxymVlasov
|
||||
- Potapy4
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
> यदि आप डॉकर के बिना स्थानीय रूप से वेबसाइट चलाना पसंद करते हैं, तो नीचे Hugo का उपयोग करके स्थानीय रूप से साइट चलाना देखें।
|
||||
|
||||
यदि आप डॉकर के बिना स्थानीय रूप से वेबसाइट चलाना पसंद करते हैं, तो नीचे दिए गए Hugo का उपयोग करके स्थानीय रूप से [साइट को चलाने](#running-the-site-locally-using-hugo) का तरीका देखें।
|
||||
यदि आप डॉकर के बिना स्थानीय रूप से वेबसाइट चलाना पसंद करते हैं, तो नीचे दिए गए Hugo का उपयोग करके स्थानीय रूप से [साइट को चलाने](#hugo-का-उपयोग-करते-हुए-स्थानीय-रूप-से-साइट-चलाना) का तरीका देखें।
|
||||
|
||||
यदि आप [डॉकर](https://www.docker.com/get-started) चला रहे हैं, तो स्थानीय रूप से `कुबेरनेट्स-ह्यूगो` Docker image बनाएँ:
|
||||
|
||||
|
|
21
README-pl.md
|
@ -22,14 +22,17 @@ Więcej informacji na temat współpracy przy tworzeniu dokumentacji znajdziesz
|
|||
* [Lokalizacja dokumentacji Kubernetes](https://kubernetes.io/docs/contribute/localization/)
|
||||
|
||||
## Różne wersje językowe `README.md`
|
||||
| | |
|
||||
|---|---|
|
||||
|[README po francusku](README-fr.md)|[README po koreańsku](README-ko.md)|
|
||||
|[README po niemiecku](README-de.md)|[README po portugalsku](README-pt.md)|
|
||||
|[README w hindi](README-hi.md)|[README po hiszpańsku](README-es.md)|
|
||||
|[README po indonezyjsku](README-id.md)|[README po chińsku](README-zh.md)|
|
||||
|[README po japońsku](README-ja.md)|[README po polsku](README-pl.md)|
|
||||
|||
|
||||
|
||||
| | |
|
||||
|----------------------------------------|----------------------------------------|
|
||||
| [README po angielsku](README.md) | [README po francusku](README-fr.md) |
|
||||
| [README po koreańsku](README-ko.md) | [README po niemiecku](README-de.md) |
|
||||
| [README po portugalsku](README-pt.md) | [README w hindi](README-hi.md) |
|
||||
| [README po hiszpańsku](README-es.md) | [README po indonezyjsku](README-id.md) |
|
||||
| [README po chińsku](README-zh.md) | [README po japońsku](README-ja.md) |
|
||||
| [README po wietnamsku](README-vi.md) | [README po rosyjsku](README-ru.md) |
|
||||
| [README po włosku](README-it.md) | [README po ukraińsku](README-uk.md) |
|
||||
| | |
|
||||
|
||||
## Jak uruchomić lokalną kopię strony przy pomocy Dockera?
|
||||
|
||||
|
@ -41,7 +44,7 @@ Zalecaną metodą uruchomienia serwisu internetowego Kubernetesa lokalnie jest u
|
|||
choco install make
|
||||
```
|
||||
|
||||
> Jeśli wolisz uruchomić serwis lokalnie bez Dockera, przeczytaj [jak uruchomić serwis lokalnie przy pomocy Hugo](#jak-uruchomić-serwis-lokalnie-przy-pomocy-hugo) poniżej.
|
||||
> Jeśli wolisz uruchomić serwis lokalnie bez Dockera, przeczytaj [jak uruchomić serwis lokalnie przy pomocy Hugo](#jak-uruchomić-lokalną-kopię-strony-przy-pomocy-hugo) poniżej.
|
||||
|
||||
Jeśli [zainstalowałeś i uruchomiłeś](https://www.docker.com/get-started) już Dockera, zbuduj obraz `kubernetes-hugo` lokalnie:
|
||||
|
||||
|
|
80
README-ru.md
|
@ -1,55 +1,9 @@
|
|||
# Документация по Kubernetes
|
||||
|
||||
[![Build Status](https://api.travis-ci.org/kubernetes/website.svg?branch=master)](https://travis-ci.org/kubernetes/website)
|
||||
[![GitHub release](https://img.shields.io/github/release/kubernetes/website.svg)](https://github.com/kubernetes/website/releases/latest)
|
||||
[![Netlify Status](https://api.netlify.com/api/v1/badges/be93b718-a6df-402a-b4a4-855ba186c97d/deploy-status)](https://app.netlify.com/sites/kubernetes-io-master-staging/deploys) [![GitHub release](https://img.shields.io/github/release/kubernetes/website.svg)](https://github.com/kubernetes/website/releases/latest)
|
||||
|
||||
Добро пожаловать! Данный репозиторий содержит все необходимые файлы для сборки [сайта Kubernetes и документации](https://kubernetes.io/). Мы благодарим вас за старания!
|
||||
|
||||
## Вклад в документацию
|
||||
|
||||
Нажмите на кнопку **Fork** в правом верхнем углу, чтобы создать копию этого репозитория в ваш GitHub-аккаунт. Эта копия называется *форк-репозиторием*. Делайте любые изменения в вашем форк-репозитории, и когда вы будете готовы опубликовать изменения, откройте форк-репозиторий и создайте новый пулреквест, чтобы уведомить нас.
|
||||
|
||||
После того, как вы отправите пулреквест, ревьювер Kubernetes даст по нему обратную связь. Вы, как автор пулреквеста, **должны обновить свой пулреквест после его рассмотрения ревьювером Kubernetes.** Вполне возможно, что более одного ревьювера Kubernetes оставят свои комментарии или даже может быть так, что новый комментарий ревьювера Kubernetes будет отличаться от первоначального назначенного ревьювера. Кроме того, в некоторых случаях один из ревьюверов может запросить технический обзор у [технического ревьювера Kubernetes](https://github.com/kubernetes/website/wiki/Tech-reviewers), если это будет необходимо. Ревьюверы сделают все возможное, чтобы как можно оперативно оставить свои предложения и пожелания, но время ответа может варьироваться в зависимости от обстоятельств.
|
||||
|
||||
Узнать подробнее о том, как поучаствовать в документации Kubernetes, вы можете по ссылкам ниже:
|
||||
|
||||
* [Начните вносить свой вклад](https://kubernetes.io/docs/contribute/start/)
|
||||
* [Просмотр локальных изменений](http://kubernetes.io/docs/contribute/intermediate#view-your-changes-locally)
|
||||
* [Использование шаблонов страниц](http://kubernetes.io/docs/contribute/style/page-templates/)
|
||||
* [Руководство по оформлению документации](http://kubernetes.io/docs/contribute/style/style-guide/)
|
||||
* [Руководство по локализации Kubernetes](https://kubernetes.io/docs/contribute/localization/)
|
||||
|
||||
## Файл `README.md` на других языках
|
||||
| | |
|
||||
|-------------------------------|-------------------------------|
|
||||
| [Французский](README-fr.md) | [Корейский](README-ko.md) |
|
||||
| [Немецкий](README-de.md) | [Португальский](README-pt.md) |
|
||||
| [Хинди](README-hi.md) | [Испанский](README-es.md) |
|
||||
| [Индонезийский](README-id.md) | [Китайский](README-zh.md) |
|
||||
| | |
|
||||
|
||||
## Запуск сайта локально с помощью Docker
|
||||
|
||||
Рекомендованный способ запуска сайта Kubernetes на локальной машине - использовать специальный образ [Docker](https://docker.com), который включает статический генератор сайтов [Hugo](https://gohugo.io).
|
||||
|
||||
> Если вы используете Windows, вам необходимо установить дополнительные инструменты через [Chocolatey](https://chocolatey.org). `choco install make`
|
||||
|
||||
> Если вы хотите запустить сайт локально без Docker, обратитесь к разделу [Запуск сайта с помощью Hugo](#запуск-сайта-с-помощью-hugo) ниже на этой странице.
|
||||
|
||||
Когда Docker [установлен и запущен](https://www.docker.com/get-started), соберите локально Docker-образ `kubernetes-hugo`, выполнив команду в консоли:
|
||||
|
||||
```bash
|
||||
make docker-image
|
||||
```
|
||||
|
||||
После того, как вы собрали образ, можно запустить сайт локально:
|
||||
|
||||
```bash
|
||||
make docker-serve
|
||||
```
|
||||
|
||||
Откройте браузер и перейдите по ссылке http://localhost:1313, чтобы открыть сайт. Если вы редактируете исходные файлы сайта, Hugo автоматически применит изменения и обновит страницу в браузере.
|
||||
|
||||
## Запуск сайта с помощью Hugo
|
||||
|
||||
Обратитесь к [официальной документации Hugo](https://gohugo.io/getting-started/installing/), чтобы установить Hugo. Убедитесь, что вы установили правильную версию Hugo, которая устанавливается в переменной окружения `HUGO_VERSION` в файле [`netlify.toml`](netlify.toml#L10).
|
||||
|
@ -57,7 +11,9 @@ make docker-serve
|
|||
После установки Hugo, чтобы запустить сайт, выполните в консоли:
|
||||
|
||||
```bash
|
||||
make serve
|
||||
git clone https://github.com/kubernetes/website.git
|
||||
cd website
|
||||
hugo server --buildFuture
|
||||
```
|
||||
|
||||
Эта команда запустит сервер Hugo на порту 1313. Откройте браузер и перейдите по ссылке http://localhost:1313, чтобы открыть сайт. Если вы отредактируете исходные файлы сайта, Hugo автоматически применит изменения и обновит страницу в браузере.
|
||||
|
@ -71,9 +27,35 @@ make serve
|
|||
- [Канал в Slack](https://kubernetes.slack.com/messages/sig-docs)
|
||||
- [Рассылка](https://groups.google.com/forum/#!forum/kubernetes-sig-docs)
|
||||
|
||||
## Вклад в документацию
|
||||
|
||||
Нажмите на кнопку **Fork** в правом верхнем углу, чтобы создать копию этого репозитория в ваш GitHub-аккаунт. Эта копия называется *форк-репозиторием*. Делайте любые изменения в вашем форк-репозитории, и когда вы будете готовы опубликовать изменения, откройте форк-репозиторий и создайте новый пулреквест, чтобы уведомить нас.
|
||||
|
||||
После того, как вы отправите пулреквест, ревьювер Kubernetes даст по нему обратную связь. Вы, как автор пулреквеста, **должны обновить свой пулреквест после его рассмотрения ревьювером Kubernetes.**
|
||||
|
||||
Вполне возможно, что более одного ревьювера Kubernetes оставят свои комментарии или даже может быть так, что новый комментарий ревьювера Kubernetes будет отличаться от первоначального назначенного ревьювера. Кроме того, в некоторых случаях один из ревьюверов может запросить технический обзор у [технического ревьювера Kubernetes](https://github.com/kubernetes/website/wiki/Tech-reviewers), если это будет необходимо. Ревьюверы сделают все возможное, чтобы как можно оперативно оставить свои предложения и пожелания, но время ответа может варьироваться в зависимости от обстоятельств.
|
||||
|
||||
Узнать подробнее о том, как поучаствовать в документации Kubernetes, вы можете по ссылкам ниже:
|
||||
|
||||
* [Начните вносить свой вклад](https://kubernetes.io/docs/contribute/)
|
||||
* [Использование шаблонов страниц](http://kubernetes.io/docs/contribute/style/page-templates/)
|
||||
* [Руководство по оформлению документации](http://kubernetes.io/docs/contribute/style/style-guide/)
|
||||
* [Руководство по локализации Kubernetes](https://kubernetes.io/docs/contribute/localization/)
|
||||
|
||||
## Файл `README.md` на других языках
|
||||
| другие языки | другие языки |
|
||||
|-------------------------------|-------------------------------|
|
||||
| [Английский](README.md) | [Французский](README-fr.md) |
|
||||
| [Корейский](README-ko.md) | [Немецкий](README-de.md) |
|
||||
| [Португальский](README-pt.md) | [Хинди](README-hi.md) |
|
||||
| [Испанский](README-es.md) | [Индонезийский](README-id.md) |
|
||||
| [Китайский](README-zh.md) | [Японский](README-ja.md) |
|
||||
| [Вьетнамский](README-vi.md) | [Итальянский](README-it.md) |
|
||||
| [Польский]( README-pl.md) | [Украинский](README-uk.md) |
|
||||
|
||||
### Кодекс поведения
|
||||
|
||||
Участие в сообществе Kubernetes регулируется [кодексом поведения Kubernetes](code-of-conduct.md).
|
||||
Участие в сообществе Kubernetes регулируется [кодексом поведения CNCF](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
||||
|
||||
## Спасибо!
|
||||
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
<!-- # The Kubernetes documentation -->
|
||||
# Документація Kubernetes
|
||||
|
||||
[![Netlify Status](https://api.netlify.com/api/v1/badges/be93b718-a6df-402a-b4a4-855ba186c97d/deploy-status)](https://app.netlify.com/sites/kubernetes-io-master-staging/deploys) [![GitHub release](https://img.shields.io/github/release/kubernetes/website.svg)](https://github.com/kubernetes/website/releases/latest)
|
||||
|
||||
<!-- This repository contains the assets required to build the [Kubernetes website and documentation](https://kubernetes.io/). We're glad that you want to contribute! -->
|
||||
Вітаємо! В цьому репозиторії міститься все необхідне для роботи над [сайтом і документацією Kubernetes](https://kubernetes.io/). Ми щасливі, що ви хочете зробити свій внесок!
|
||||
|
||||
<!-- ## Running the website locally using Hugo -->
|
||||
## Запуск сайту локально зa допомогою Hugo
|
||||
|
||||
<!-- See the [official Hugo documentation](https://gohugo.io/getting-started/installing/) for Hugo installation instructions. Make sure to install the Hugo extended version specified by the `HUGO_VERSION` environment variable in the [`netlify.toml`](netlify.toml#L10) file. -->
|
||||
Для інструкцій з встановлення Hugo дивіться [офіційну документацію](https://gohugo.io/getting-started/installing/). Обов’язково встановіть розширену версію Hugo, яка позначена змінною оточення `HUGO_VERSION` у файлі [`netlify.toml`](netlify.toml#L10).
|
||||
|
||||
<!-- To run the website locally when you have Hugo installed: -->
|
||||
Після встановлення Hugo, запустіть сайт локально командою:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/kubernetes/website.git
|
||||
cd website
|
||||
hugo server --buildFuture
|
||||
```
|
||||
|
||||
<!-- This will start the local Hugo server on port 1313. Open up your browser to http://localhost:1313 to view the website. As you make changes to the source files, Hugo updates the website and forces a browser refresh. -->
|
||||
Команда запустить локальний Hugo-сервер на порту 1313. Відкрийте у своєму браузері http://localhost:1313, щоб побачити сайт. По мірі того, як ви змінюєте вихідний код, Hugo актуалізує сайт відповідно до внесених змін і оновлює сторінку у браузері.
|
||||
|
||||
<!-- ## Get involved with SIG Docs -->
|
||||
## Спільнота, обговорення, внесок і підтримка
|
||||
|
||||
<!-- Learn more about SIG Docs Kubernetes community and meetings on the [community page](https://github.com/kubernetes/community/tree/master/sig-docs#meetings). -->
|
||||
Дізнайтеся, як долучитися до спільноти Kubernetes на [сторінці спільноти](http://kubernetes.io/community/).
|
||||
|
||||
<!-- You can also reach the maintainers of this project at: -->
|
||||
Для зв’язку із супроводжуючими проекту скористайтеся:
|
||||
|
||||
- [Slack](https://kubernetes.slack.com/messages/sig-docs)
|
||||
- [Поштова розсилка](https://groups.google.com/forum/#!forum/kubernetes-sig-docs)
|
||||
|
||||
<!-- ## Contributing to the docs -->
|
||||
## Внесок у документацію
|
||||
|
||||
<!-- You can click the **Fork** button in the upper-right area of the screen to create a copy of this repository in your GitHub account. This copy is called a *fork*. Make any changes you want in your fork, and when you are ready to send those changes to us, go to your fork and create a new pull request to let us know about it. -->
|
||||
Ви можете створити копію цього репозиторія у своєму акаунті на GitHub, натиснувши на кнопку **Fork**, що розташована справа зверху. Ця копія називатиметься *fork* (відгалуження). Зробіть будь-які необхідні зміни у своєму відгалуженні. Коли ви будете готові надіслати їх нам, перейдіть до свого відгалуження і створіть новий pull request, щоб сповістити нас.
|
||||
|
||||
<!-- Once your pull request is created, a Kubernetes reviewer will take responsibility for providing clear, actionable feedback. As the owner of the pull request, **it is your responsibility to modify your pull request to address the feedback that has been provided to you by the Kubernetes reviewer.** -->
|
||||
Після того, як ви створили pull request, рецензент Kubernetes зобов’язується надати вам по ньому чіткий і конструктивний коментар. **Ваш обов’язок як творця pull request - відкоригувати його відповідно до зауважень рецензента Kubernetes.**
|
||||
|
||||
<!-- Also, note that you may end up having more than one Kubernetes reviewer provide you feedback or you may end up getting feedback from a Kubernetes reviewer that is different than the one initially assigned to provide you feedback. -->
|
||||
Також, зауважте: може статися так, що ви отримаєте коментарі від декількох рецензентів Kubernetes або від іншого рецензента, ніж той, якого вам було призначено від початку.
|
||||
|
||||
<!-- Furthermore, in some cases, one of your reviewers might ask for a technical review from a Kubernetes tech reviewer when needed. Reviewers will do their best to provide feedback in a timely fashion but response time can vary based on circumstances. -->
|
||||
Крім того, за потреби один із ваших рецензентів може запросити технічну перевірку від одного з технічних рецензентів Kubernetes, коли це необхідно. Рецензенти намагатимуться відреагувати вчасно, проте час відповіді може відрізнятися в залежності від обставин.
|
||||
|
||||
<!-- For more information about contributing to the Kubernetes documentation, see: -->
|
||||
Більше інформації про внесок у документацію Kubernetes ви знайдете у наступних джерелах:
|
||||
|
||||
* [Внесок: з чого почати](https://kubernetes.io/docs/contribute/)
|
||||
* [Використання шаблонів сторінок](http://kubernetes.io/docs/contribute/style/page-templates/)
|
||||
* [Керівництво зі стилю оформлення документації](http://kubernetes.io/docs/contribute/style/style-guide/)
|
||||
* [Переклад документації Kubernetes іншими мовами](https://kubernetes.io/docs/contribute/localization/)
|
||||
|
||||
<!-- ## Localization `README.md`'s -->
|
||||
## Файл `README.md` іншими мовами
|
||||
|
||||
| інші мови | інші мови |
|
||||
|-------------------------------|-------------------------------|
|
||||
| [Англійська](README.md) | [Французька](README-fr.md) |
|
||||
| [Корейська](README-ko.md) | [Німецька](README-de.md) |
|
||||
| [Португальська](README-pt.md) | [Хінді](README-hi.md) |
|
||||
| [Іспанська](README-es.md) | [Індонезійська](README-id.md) |
|
||||
| [Китайська](README-zh.md) | [Японська](README-ja.md) |
|
||||
| [В'єтнамська](README-vi.md) | [Російська](README-ru.md) |
|
||||
| [Італійська](README-it.md) | [Польська](README-pl.md) |
|
||||
|
||||
<!-- ## Code of conduct -->
|
||||
## Кодекс поведінки
|
||||
|
||||
<!-- Participation in the Kubernetes community is governed by the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). -->
|
||||
Участь у спільноті Kubernetes визначається правилами [Кодексу поведінки СNCF](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
||||
|
||||
<!-- ## Thank you! -->
|
||||
## Дякуємо!
|
||||
|
||||
<!-- Kubernetes thrives on community participation, and we appreciate your contributions to our website and our documentation! -->
|
||||
Долучення до спільноти - запорука успішного розвитку Kubernetes. Ми цінуємо ваш внесок у наш сайт і документацію!
|
108
README.md
|
@ -1,83 +1,65 @@
|
|||
# The Kubernetes documentation
|
||||
|
||||
[![Build Status](https://api.travis-ci.org/kubernetes/website.svg?branch=master)](https://travis-ci.org/kubernetes/website)
|
||||
[![GitHub release](https://img.shields.io/github/release/kubernetes/website.svg)](https://github.com/kubernetes/website/releases/latest)
|
||||
[![Netlify Status](https://api.netlify.com/api/v1/badges/be93b718-a6df-402a-b4a4-855ba186c97d/deploy-status)](https://app.netlify.com/sites/kubernetes-io-master-staging/deploys) [![GitHub release](https://img.shields.io/github/release/kubernetes/website.svg)](https://github.com/kubernetes/website/releases/latest)
|
||||
|
||||
Welcome! This repository houses all of the assets required to build the [Kubernetes website and documentation](https://kubernetes.io/). We're glad that you want to contribute!
|
||||
This repository contains the assets required to build the [Kubernetes website and documentation](https://kubernetes.io/). We're glad that you want to contribute!
|
||||
|
||||
## Running the website locally using Hugo
|
||||
|
||||
See the [official Hugo documentation](https://gohugo.io/getting-started/installing/) for Hugo installation instructions. Make sure to install the Hugo extended version specified by the `HUGO_VERSION` environment variable in the [`netlify.toml`](netlify.toml#L10) file.
|
||||
|
||||
To run the website locally when you have Hugo installed:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/kubernetes/website.git
|
||||
cd website
|
||||
hugo server --buildFuture
|
||||
```
|
||||
|
||||
This will start the local Hugo server on port 1313. Open up your browser to http://localhost:1313 to view the website. As you make changes to the source files, Hugo updates the website and forces a browser refresh.
|
||||
|
||||
## Get involved with SIG Docs
|
||||
|
||||
Learn more about SIG Docs Kubernetes community and meetings on the [community page](https://github.com/kubernetes/community/tree/master/sig-docs#meetings).
|
||||
|
||||
You can also reach the maintainers of this project at:
|
||||
|
||||
- [Slack](https://kubernetes.slack.com/messages/sig-docs)
|
||||
- [Mailing List](https://groups.google.com/forum/#!forum/kubernetes-sig-docs)
|
||||
|
||||
## Contributing to the docs
|
||||
|
||||
You can click the **Fork** button in the upper-right area of the screen to create a copy of this repository in your GitHub account. This copy is called a *fork*. Make any changes you want in your fork, and when you are ready to send those changes to us, go to your fork and create a new pull request to let us know about it.
|
||||
|
||||
Once your pull request is created, a Kubernetes reviewer will take responsibility for providing clear, actionable feedback. As the owner of the pull request, **it is your responsibility to modify your pull request to address the feedback that has been provided to you by the Kubernetes reviewer.** Also, note that you may end up having more than one Kubernetes reviewer provide you feedback or you may end up getting feedback from a Kubernetes reviewer that is different than the one initially assigned to provide you feedback. Furthermore, in some cases, one of your reviewers might ask for a technical review from a [Kubernetes tech reviewer](https://github.com/kubernetes/website/wiki/Tech-reviewers) when needed. Reviewers will do their best to provide feedback in a timely fashion but response time can vary based on circumstances.
|
||||
Once your pull request is created, a Kubernetes reviewer will take responsibility for providing clear, actionable feedback. As the owner of the pull request, **it is your responsibility to modify your pull request to address the feedback that has been provided to you by the Kubernetes reviewer.**
|
||||
|
||||
Also, note that you may end up having more than one Kubernetes reviewer provide you feedback or you may end up getting feedback from a Kubernetes reviewer that is different than the one initially assigned to provide you feedback.
|
||||
|
||||
Furthermore, in some cases, one of your reviewers might ask for a technical review from a Kubernetes tech reviewer when needed. Reviewers will do their best to provide feedback in a timely fashion but response time can vary based on circumstances.
|
||||
|
||||
For more information about contributing to the Kubernetes documentation, see:
|
||||
|
||||
* [Start contributing](https://kubernetes.io/docs/contribute/start/)
|
||||
* [Staging Your Documentation Changes](http://kubernetes.io/docs/contribute/intermediate#view-your-changes-locally)
|
||||
* [Using Page Templates](http://kubernetes.io/docs/contribute/style/page-templates/)
|
||||
* [Documentation Style Guide](http://kubernetes.io/docs/contribute/style/style-guide/)
|
||||
* [Contribute to Kubernetes docs](https://kubernetes.io/docs/contribute/)
|
||||
* [Using Page Templates](https://kubernetes.io/docs/contribute/style/page-templates/)
|
||||
* [Documentation Style Guide](https://kubernetes.io/docs/contribute/style/style-guide/)
|
||||
* [Localizing Kubernetes Documentation](https://kubernetes.io/docs/contribute/localization/)
|
||||
|
||||
## Localization `README.md`'s
|
||||
| | |
|
||||
|
||||
| Language | Language |
|
||||
|---|---|
|
||||
|[French README](README-fr.md)|[Korean README](README-ko.md)|
|
||||
|[German README](README-de.md)|[Portuguese README](README-pt.md)|
|
||||
|[Hindi README](README-hi.md)|[Spanish README](README-es.md)|
|
||||
|[Indonesian README](README-id.md)|[Chinese README](README-zh.md)|
|
||||
|[Japanese README](README-ja.md)|[Vietnamese README](README-vi.md)|
|
||||
|[Russian README](README-ru.md)|[Italian README](README-it.md)|
|
||||
|[Polish README](README-pl.md)||
|
||||
|||
|
||||
|[Chinese](README-zh.md)|[Korean](README-ko.md)|
|
||||
|[French](README-fr.md)|[Polish](README-pl.md)|
|
||||
|[German](README-de.md)|[Portuguese](README-pt.md)|
|
||||
|[Hindi](README-hi.md)|[Russian](README-ru.md)|
|
||||
|[Indonesian](README-id.md)|[Spanish](README-es.md)|
|
||||
|[Italian](README-it.md)|[Ukrainian](README-uk.md)|
|
||||
|[Japanese](README-ja.md)|[Vietnamese](README-vi.md)|
|
||||
|
||||
## Running the website locally using Docker
|
||||
## Code of conduct
|
||||
|
||||
The recommended way to run the Kubernetes website locally is to run a specialized [Docker](https://docker.com) image that includes the [Hugo](https://gohugo.io) static website generator.
|
||||
|
||||
> If you are running on Windows, you'll need a few more tools which you can install with [Chocolatey](https://chocolatey.org). `choco install make`
|
||||
|
||||
> If you'd prefer to run the website locally without Docker, see [Running the website locally using Hugo](#running-the-website-locally-using-hugo) below.
|
||||
|
||||
If you have Docker [up and running](https://www.docker.com/get-started), build the `kubernetes-hugo` Docker image locally:
|
||||
|
||||
```bash
|
||||
make docker-image
|
||||
```
|
||||
|
||||
Once the image has been built, you can run the website locally:
|
||||
|
||||
```bash
|
||||
make docker-serve
|
||||
```
|
||||
|
||||
Open up your browser to http://localhost:1313 to view the website. As you make changes to the source files, Hugo updates the website and forces a browser refresh.
|
||||
|
||||
## Running the website locally using Hugo
|
||||
|
||||
See the [official Hugo documentation](https://gohugo.io/getting-started/installing/) for Hugo installation instructions. Make sure to install the Hugo extended version specified by the `HUGO_VERSION` environment variable in the [`netlify.toml`](netlify.toml#L9) file.
|
||||
|
||||
To run the website locally when you have Hugo installed:
|
||||
|
||||
```bash
|
||||
make serve
|
||||
```
|
||||
|
||||
This will start the local Hugo server on port 1313. Open up your browser to http://localhost:1313 to view the website. As you make changes to the source files, Hugo updates the website and forces a browser refresh.
|
||||
|
||||
## Community, discussion, contribution, and support
|
||||
|
||||
Learn how to engage with the Kubernetes community on the [community page](http://kubernetes.io/community/).
|
||||
|
||||
You can reach the maintainers of this project at:
|
||||
|
||||
- [Slack](https://kubernetes.slack.com/messages/sig-docs)
|
||||
- [Mailing List](https://groups.google.com/forum/#!forum/kubernetes-sig-docs)
|
||||
|
||||
### Code of conduct
|
||||
|
||||
Participation in the Kubernetes community is governed by the [Kubernetes Code of Conduct](code-of-conduct.md).
|
||||
Participation in the Kubernetes community is governed by the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
||||
|
||||
## Thank you!
|
||||
|
||||
Kubernetes thrives on community participation, and we appreciate your contributions to our website and our documentation!
|
||||
Kubernetes thrives on community participation, and we appreciate your contributions to our website and our documentation!
|
|
@ -139,6 +139,9 @@ header
|
|||
border-spacing: 0
|
||||
margin-top: 30px
|
||||
margin-bottom: 30px
|
||||
@media screen and (max-width: 425px)
|
||||
display: block
|
||||
overflow-x: auto
|
||||
|
||||
thead
|
||||
border-bottom: 2px solid #ccc
|
||||
|
@ -439,6 +442,7 @@ footer
|
|||
width: 100%
|
||||
background-image: url(/images/texture.png)
|
||||
background-color: $dark-grey
|
||||
overflow-x: hidden
|
||||
|
||||
.main-section
|
||||
padding: 20px 0
|
||||
|
@ -1214,7 +1218,7 @@ $feature-box-div-margin-bottom: 40px
|
|||
margin-bottom: 20px
|
||||
|
||||
#desktopKCButton
|
||||
position: relative
|
||||
position: absolute
|
||||
font-size: 18px
|
||||
background-color: $dark-grey
|
||||
border-radius: 8px
|
||||
|
@ -1802,6 +1806,7 @@ $feature-box-div-margin-bottom: 40px
|
|||
|
||||
img
|
||||
padding-bottom: 1rem
|
||||
max-width: 100%
|
||||
|
||||
div
|
||||
position: relative
|
||||
|
|
|
@ -2,7 +2,7 @@ $main-max-width: 1200px
|
|||
$vendor-strip-height: 44px
|
||||
$video-section-height: 550px
|
||||
|
||||
@media screen and (min-width: 1025px)
|
||||
@media screen and (min-width: 1100px)
|
||||
#hamburger
|
||||
display: none
|
||||
|
||||
|
|
63
config.toml
|
@ -14,23 +14,39 @@ contentDir = "content/en"
|
|||
|
||||
timeout = 3000
|
||||
|
||||
# Highlighting config.
|
||||
pygmentsCodeFences = true
|
||||
pygmentsUseClasses = false
|
||||
# See https://help.farbox.com/pygments.html
|
||||
pygmentsStyle = "emacs"
|
||||
|
||||
# Enable Git variables like commit, lastmod
|
||||
enableGitInfo = true
|
||||
|
||||
# Norwegian ("no") is sometimes but not currently used for testing.
|
||||
# Hindi is disabled because it's currently in development.
|
||||
# Italian is disabled until it meets minimum standards for quality.
|
||||
disableLanguages = ["hi", "it", "no"]
|
||||
disableLanguages = ["hi", "no"]
|
||||
|
||||
[blackfriday]
|
||||
hrefTargetBlank = true
|
||||
fractions = false
|
||||
[markup]
|
||||
[markup.goldmark]
|
||||
[markup.goldmark.extensions]
|
||||
definitionList = true
|
||||
table = true
|
||||
typographer = false
|
||||
[markup.goldmark.parser]
|
||||
attribute = true
|
||||
autoHeadingID = true
|
||||
autoHeadingIDType = "blackfriday"
|
||||
[markup.goldmark.renderer]
|
||||
unsafe = true
|
||||
[markup.highlight]
|
||||
codeFences = true
|
||||
guessSyntax = false
|
||||
hl_Lines = ""
|
||||
lineNoStart = 1
|
||||
lineNos = false
|
||||
lineNumbersInTable = true
|
||||
noClasses = true
|
||||
style = "emacs"
|
||||
tabWidth = 4
|
||||
[markup.tableOfContents]
|
||||
endLevel = 2
|
||||
ordered = false
|
||||
startLevel = 2
|
||||
|
||||
[frontmatter]
|
||||
date = ["date", ":filename", "publishDate", "lastmod"]
|
||||
|
@ -78,11 +94,10 @@ nextUrl = "https://kubernetes-io-vnext-staging.netlify.com/"
|
|||
githubWebsiteRepo = "github.com/kubernetes/website"
|
||||
githubWebsiteRaw = "raw.githubusercontent.com/kubernetes/website"
|
||||
|
||||
# param for displaying an announcement block on every page; see PR #16210
|
||||
announcement = false
|
||||
# announcement_message is only displayed when announcement = true; update with your specific message
|
||||
announcement_message = "The Kubernetes Documentation team would like your feedback! Please take a <a href='https://www.surveymonkey.com/r/8R237FN' target='_blank'>short survey</a> so we can improve the Kubernetes online documentation."
|
||||
|
||||
# param for displaying an announcement block on every page.
|
||||
# See /i18n/en.toml for message text and title.
|
||||
announcement = true
|
||||
announcement_bg = "#000000" #choose a dark color – text is white
|
||||
|
||||
[params.pushAssets]
|
||||
css = [
|
||||
|
@ -187,8 +202,8 @@ language_alternatives = ["en"]
|
|||
|
||||
[languages.it]
|
||||
title = "Kubernetes"
|
||||
description = "Production-Grade Container Orchestration"
|
||||
languageName ="Italian"
|
||||
description = "Orchestrazione di Container in produzione"
|
||||
languageName = "Italiano"
|
||||
weight = 6
|
||||
contentDir = "content/it"
|
||||
|
||||
|
@ -298,3 +313,15 @@ contentDir = "content/pl"
|
|||
time_format_blog = "01.02.2006"
|
||||
# A list of language codes to look for untranslated content, ordered from left to right.
|
||||
language_alternatives = ["en"]
|
||||
|
||||
[languages.uk]
|
||||
title = "Kubernetes"
|
||||
description = "Довершена система оркестрації контейнерів"
|
||||
languageName = "Українська"
|
||||
weight = 14
|
||||
contentDir = "content/uk"
|
||||
|
||||
[languages.uk.params]
|
||||
time_format_blog = "02.01.2006"
|
||||
# A list of language codes to look for untranslated content, ordered from left to right.
|
||||
language_alternatives = ["en"]
|
||||
|
|
|
@ -14,23 +14,23 @@ Es gruppiert Container, aus denen sich eine Anwendung zusammensetzt, in logische
|
|||
{{% /blocks/feature %}}
|
||||
|
||||
{{% blocks/feature image="scalable" %}}
|
||||
#### Planet Scale
|
||||
#### Ausgereift
|
||||
|
||||
Kubernetes basiert auf denselben Prinzipien, die es Google ermöglichen, Milliarden von Containern pro Woche zu betreiben.
|
||||
|
||||
{{% /blocks/feature %}}
|
||||
|
||||
{{% blocks/feature image="blocks" %}}
|
||||
#### Never Outgrow
|
||||
#### Mitwachsend
|
||||
|
||||
Unabhängig davon, ob Sie lokal testen oder ein globales Unternehmen betreiben, die Flexibilität von Kubernetes wächst mit Ihnen, um Ihre Anwendungen konsistent und einfach bereitzustellen, unabhängig von der Komplexität Ihrer Anforderungen.
|
||||
Unabhängig davon, ob Du lokal testest oder ein globales Unternehmen betreibst: Die Flexibilität von Kubernetes wächst mit Dir, um Deine Anwendungen konsistent und einfach bereitzustellen - Unabhängig von der Komplexität Deiner Anforderungen.
|
||||
|
||||
{{% /blocks/feature %}}
|
||||
|
||||
{{% blocks/feature image="suitcase" %}}
|
||||
#### Run Anywhere
|
||||
#### Überall Lauffähig
|
||||
|
||||
Kubernetes ist Open Source und bietet Ihnen die Freiheit, die Infrastruktur vor Ort, Hybrid oder Public Cloud zu nutzen. So können Sie Workloads mühelos dorthin verschieben, wo es Ihnen wichtig ist.
|
||||
Kubernetes ist Open Source und bietet Dir die Freiheit, die Infrastruktur vor Ort, Hybrid oder Public Cloud zu nutzen. So kannst Du Workloads mühelos dorthin verschieben, wo es Dir wichtig ist.
|
||||
|
||||
{{% /blocks/feature %}}
|
||||
|
||||
|
@ -39,17 +39,17 @@ Kubernetes ist Open Source und bietet Ihnen die Freiheit, die Infrastruktur vor
|
|||
{{< blocks/section id="video" background-image="kub_video_banner_homepage" >}}
|
||||
<div class="light-text">
|
||||
<h2>Die Herausforderungen bei der Migration von über 150 Microservices auf Kubernetes</h2>
|
||||
<p>Von Sarah Wells, technischer Direktor für Betrieb und Zuverlässigkeit, Financial Times</p>
|
||||
<p>Von Sarah Wells, technische Direktorin für Betrieb und Zuverlässigkeit, Financial Times</p>
|
||||
<button id="desktopShowVideoButton" onclick="kub.showVideo()">Video ansehen</button>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<a href="https://events.linuxfoundation.org/events/kubecon-cloudnativecon-europe-2020/" button id="desktopKCButton">Besuchen Sie die KubeCon vom 30 März-2 Apr. 2020 in Amsterdam</a>
|
||||
<a href="https://events.linuxfoundation.org/kubecon-cloudnativecon-europe/?utm_source=kubernetes.io&utm_medium=nav&utm_campaign=kccnceu20" button id="desktopKCButton">Besuche die KubeCon - 13-16 August 2020 in Amsterdam</a>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<a href="https://www.lfasiallc.cn/kubecon-cloudnativecon-open-source-summit-china/" button id="desktopKCButton">Besuchen Sie die KubeCon vom 28-30 Juli 2020 in Shanghai</a>
|
||||
<a href="https://events.linuxfoundation.org/kubecon-cloudnativecon-north-america/?utm_source=kubernetes.io&utm_medium=nav&utm_campaign=kccncna20" button id="desktopKCButton">Besuche die KubeCon - 17-20 November 2020 in Boston</a>
|
||||
</div>
|
||||
<div id="videoPlayer">
|
||||
<iframe data-url="https://www.youtube.com/embed/H06qrNmGqyE?autoplay=1" frameborder="0" allowfullscreen></iframe>
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
---
|
||||
title: Konzepte
|
||||
main_menu: true
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
weight: 40
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
Im Abschnitt Konzepte erfahren Sie mehr über die Bestandteile des Kubernetes-Systems und die Abstraktionen, die Kubernetes zur Verwaltung Ihres Clusters zur Verfügung stellt. Sie erhalten zudem ein tieferes Verständnis der Funktionsweise von Kubernetes.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Überblick
|
||||
|
||||
|
@ -65,11 +65,12 @@ Die Nodes in einem Cluster sind die Maschinen (VMs, physische Server usw.), auf
|
|||
|
||||
* [Anmerkungen](/docs/concepts/overview/working-with-objects/annotations/)
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
|
||||
Wenn Sie eine Konzeptseite schreiben möchten, lesen Sie [Seitenvorlagen verwenden](/docs/home/contribute/page-templates/)
|
||||
für Informationen zum Konzeptseitentyp und zur Dokumentations Vorlage.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
---
|
||||
title: Zugrunde liegende Konzepte des Cloud Controller Manager
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
weight: 30
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
Das Konzept des Cloud Controller Managers (CCM) (nicht zu verwechseln mit der Binärdatei) wurde ursprünglich entwickelt, um Cloud-spezifischen Anbieter Code und den Kubernetes Kern unabhängig voneinander entwickeln zu können. Der Cloud Controller Manager läuft zusammen mit anderen Master Komponenten wie dem Kubernetes Controller Manager, dem API-Server und dem Scheduler auf dem Host. Es kann auch als Kubernetes Addon gestartet werden, in diesem Fall läuft er auf Kubernetes.
|
||||
|
||||
Das Design des Cloud Controller Managers basiert auf einem Plugin Mechanismus, der es neuen Cloud Anbietern ermöglicht, sich mit Kubernetes einfach über Plugins zu integrieren. Es gibt Pläne für die Einbindung neuer Cloud Anbieter auf Kubernetes und für die Migration von Cloud Anbietern vom alten Modell auf das neue CCM-Modell.
|
||||
|
@ -15,10 +15,10 @@ Die Architektur eines Kubernetes Clusters ohne den Cloud Controller Manager sieh
|
|||
|
||||
![Pre CCM Kube Arch](/images/docs/pre-ccm-arch.png)
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Design
|
||||
|
||||
|
@ -235,4 +235,4 @@ Die folgenden Cloud Anbieter haben CCMs implementiert:
|
|||
|
||||
Eine vollständige Anleitung zur Konfiguration und zum Betrieb des CCM findest du [hier](/docs/tasks/administer-cluster/running-cloud-controller/#cloud-controller-manager).
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
---
|
||||
title: Master-Node Kommunikation
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
weight: 20
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
Dieses Dokument katalogisiert die Kommunikationspfade zwischen dem Master (eigentlich dem Apiserver) und des Kubernetes-Clusters.
|
||||
Die Absicht besteht darin, Benutzern die Möglichkeit zu geben, ihre Installation so anzupassen, dass die Netzwerkkonfiguration so abgesichert wird, dass der Cluster in einem nicht vertrauenswürdigen Netzwerk (oder mit vollständig öffentlichen IP-Adressen eines Cloud-Providers) ausgeführt werden kann.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Cluster zum Master
|
||||
|
||||
|
@ -69,4 +69,4 @@ Dieser Tunnel stellt sicher, dass der Datenverkehr nicht außerhalb des Netzwerk
|
|||
|
||||
SSH-Tunnel werden zur Zeit nicht unterstützt. Sie sollten also nicht verwendet werden, sei denn, man weiß, was man tut. Ein Ersatz für diesen Kommunikationskanal wird entwickelt.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
---
|
||||
title: Nodes
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
weight: 10
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
Ein Knoten (Node in Englisch) ist eine Arbeitsmaschine in Kubernetes, früher als `minion` bekannt. Ein Node
|
||||
kann je nach Cluster eine VM oder eine physische Maschine sein. Jeder Node enthält
|
||||
|
@ -13,10 +13,10 @@ und wird von den Master-Komponenten verwaltet.
|
|||
Die Dienste auf einem Node umfassen die [Container Runtime](/docs/concepts/overview/components/#node-components), das Kubelet und den Kube-Proxy.
|
||||
Weitere Informationen finden Sie im Abschnitt Kubernetes Node in der Architekturdesign-Dokumentation.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Node Status
|
||||
|
||||
|
@ -244,4 +244,4 @@ Wenn Sie Ressourcen explizit für Nicht-Pod-Prozesse reservieren möchten, folge
|
|||
Node ist eine Top-Level-Ressource in der Kubernetes-REST-API. Weitere Details zum API-Objekt finden Sie unter:
|
||||
[Node API object](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#node-v1-core).
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
---
|
||||
title: Addons Installieren
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
|
||||
Add-Ons erweitern die Funktionalität von Kubernetes.
|
||||
|
@ -12,10 +12,10 @@ Diese Seite gibt eine Übersicht über einige verfügbare Add-Ons und verweist a
|
|||
|
||||
Die Add-Ons in den einzelnen Kategorien sind alphabetisch sortiert - Die Reihenfolge impliziert keine bevorzugung einzelner Projekte.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Networking und Network Policy
|
||||
|
||||
|
@ -53,4 +53,4 @@ Es gibt einige weitere Add-Ons die in dem abgekündigten [cluster/addons](https:
|
|||
|
||||
Add-Ons die ordentlich gewartet werden dürfen gerne hier aufgezählt werden. Wir freuen uns auf PRs!
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
---
|
||||
title: Controller Manager Metriken
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
weight: 100
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
Controller Manager Metriken liefern wichtige Erkenntnisse über die Leistung und den Zustand von den Controller Managern.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
## Was sind Controller Manager Metriken
|
||||
|
||||
Die Kennzahlen des Controller Managers liefert wichtige Erkenntnisse über die Leistung und den Zustand des Controller Managers.
|
||||
|
@ -38,4 +38,3 @@ Die Metriken werden im [Prometheus Format](https://prometheus.io/docs/instrument
|
|||
|
||||
In einer Produktionsumgebung können Sie Prometheus oder einen anderen Metrik Scraper konfigurieren, um diese Metriken regelmäßig zu sammeln und in einer Art Zeitreihen Datenbank verfügbar zu machen.
|
||||
|
||||
{{% /capture %}}
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
title: Proxies in Kubernetes
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
weight: 90
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
Auf dieser Seite werden die im Kubernetes verwendeten Proxies erläutert.
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Proxies
|
||||
|
||||
|
@ -61,4 +61,3 @@ Kubernetes Benutzer müssen sich in der Regel um nichts anderes als die ersten b
|
|||
|
||||
Proxies haben die Möglichkeit der Umleitung (redirect) ersetzt. Umleitungen sind veraltet.
|
||||
|
||||
{{% /capture %}}
|
|
@ -1,23 +1,23 @@
|
|||
---
|
||||
title: Images
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
weight: 10
|
||||
---
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
Sie erstellen ihr Docker Image und laden es in eine Registry hoch bevor es in einem Kubernetes Pod referenziert werden kann.
|
||||
Sie erstellen ihr Docker Image und laden es in eine Registry hoch, bevor es in einem Kubernetes Pod referenziert werden kann.
|
||||
|
||||
Die `image` Eigenschaft eines Containers unterstüzt die gleiche Syntax wie die des `docker` Kommandos, inklusive privater Registries und Tags.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Aktualisieren von Images
|
||||
|
||||
Die Standardregel für das Herunterladen von Images ist `IfNotPresent`, dies führt dazu das dass Kubelet Images überspringt die bereits auf einem Node vorliegen.
|
||||
Wenn sie stattdessen möchten das ein Image immer forciert heruntergeladen wird, können sie folgendes tun:
|
||||
Die Standardregel für das Herunterladen von Images ist `IfNotPresent`, dies führt dazu, dass das Kubelet Images überspringt, die bereits auf einem Node vorliegen.
|
||||
Wenn sie stattdessen möchten, dass ein Image immer forciert heruntergeladen wird, können sie folgendes tun:
|
||||
|
||||
|
||||
- Die `imagePullPolicy` des Containers auf `Always` setzen.
|
||||
|
@ -25,7 +25,7 @@ Wenn sie stattdessen möchten das ein Image immer forciert heruntergeladen wird,
|
|||
- Die `imagePullPolicy` und den Tag des Images auslassen.
|
||||
- Den [AlwaysPullImages](/docs/reference/access-authn-authz/admission-controllers/#alwayspullimages) Admission Controller aktivieren.
|
||||
|
||||
Beachten Sie das die die Nutzung des `:latest` Tags vermeiden sollten, weitere Informationen siehe: [Best Practices for Configuration](/docs/concepts/configuration/overview/#container-images).
|
||||
Beachten Sie, dass Sie die Nutzung des `:latest` Tags vermeiden sollten. Für weitere Informationen siehe: [Best Practices for Configuration](/docs/concepts/configuration/overview/#container-images).
|
||||
|
||||
## Multi-Architektur Images mit Manifesten bauen
|
||||
|
||||
|
@ -38,17 +38,17 @@ https://docs.docker.com/edge/engine/reference/commandline/manifest/
|
|||
Hier einige Beispiele wie wir dies in unserem Build - Prozess nutzen:
|
||||
https://cs.k8s.io/?q=docker%20manifest%20(create%7Cpush%7Cannotate)&i=nope&files=&repos=
|
||||
|
||||
Diese Kommandos basieren rein auf dem Docker Kommandozeileninterface und werden auch damit ausgeführt. Sie sollten entweder die Datei `$HOME/.docker/config.json` bearbeiten und den `experimental` Schlüssel auf `enabled`setzen, oder einfach die Umgebungsvariable `DOCKER_CLI_EXPERIMENTAL` auf `enabled`setzen wenn Sie das Docker Kommandozeileninterface aufrufen.
|
||||
Diese Kommandos basieren rein auf dem Docker Kommandozeileninterface und werden auch damit ausgeführt. Sie sollten entweder die Datei `$HOME/.docker/config.json` bearbeiten und den `experimental` Schlüssel auf `enabled` setzen, oder einfach die Umgebungsvariable `DOCKER_CLI_EXPERIMENTAL` auf `enabled` setzen, wenn Sie das Docker Kommandozeileninterface aufrufen.
|
||||
|
||||
|
||||
{{< note >}}
|
||||
Nutzen die bitte Docker *18.06 oder neuer*, ältere Versionen haben entweder bugs oder unterstützen die experimentelle Kommandozeilenoption nicht. Beispiel: https://github.com/docker/cli/issues/1135 verursacht Probleme unter containerd.
|
||||
Nutzen die bitte Docker *18.06 oder neuer*, ältere Versionen haben entweder Bugs oder unterstützen die experimentelle Kommandozeilenoption nicht. Beispiel: https://github.com/docker/cli/issues/1135 verursacht Probleme unter containerd.
|
||||
|
||||
{{< /note >}}
|
||||
|
||||
Wenn mit alten Manifesten Probleme auftreten können sie die alten Manifeste in `$HOME/.docker/manifests` entfernen um von vorne zu beginnen.
|
||||
Wenn mit alten Manifesten Probleme auftreten, können sie die alten Manifeste in `$HOME/.docker/manifests` entfernen, um von vorne zu beginnen.
|
||||
|
||||
Für Kubernetes selbst haben wir typischerweise Images mit dem Suffix `-$(ARCH)` genutzt. Um die Abwärtskompatibilität zu erhalten bitten wir Sie die älteren Images mit diesen Suffixen zu generieren. Die Idee dahinter ist z.B. das `pause` image zu generieren, welches das Manifest für alle Architekturen hat, `pause-amd64` wäre dann abwärtskompatibel zu älteren Konfigurationen, oder YAML - Dateien die ein Image mit Suffixen hart kodiert haben.
|
||||
Für Kubernetes selbst nutzen wir typischerweise Images mit dem Suffix `-$(ARCH)`. Um die Abwärtskompatibilität zu erhalten, bitten wir Sie, die älteren Images mit diesen Suffixen zu generieren. Die Idee dahinter ist z.B., das `pause` image zu generieren, welches das Manifest für alle Architekturen hat, `pause-amd64` wäre dann abwärtskompatibel zu älteren Konfigurationen, oder YAML - Dateien, die ein Image mit Suffixen hart kodiert enthalten.
|
||||
|
||||
|
||||
## Nutzung einer privaten Registry
|
||||
|
@ -73,32 +73,32 @@ Authentifizierungsdaten können auf verschiedene Weisen hinterlegt werden:
|
|||
- Setzt die Konfiguration der Nodes durch einen Cluster - Aministrator voraus
|
||||
- Im Voraus heruntergeladene Images
|
||||
- Alle Pods können jedes gecachte Image auf einem Node nutzen
|
||||
- Setzt root - Zugriff auf allen Nodes zum einrichten voraus
|
||||
- Spezifizieren eines ImagePullSecrets bei einem Pod
|
||||
- Nur Pods die eigene Schlüssel vorhalten haben Zugriff auf eine private Registry
|
||||
- Setzt root - Zugriff auf allen Nodes zum Einrichten voraus
|
||||
- Spezifizieren eines ImagePullSecrets auf einem Pod
|
||||
- Nur Pods, die eigene Secret tragen, haben Zugriff auf eine private Registry
|
||||
|
||||
Jeder Option wird im Folgenden im Detail beschrieben
|
||||
Jede Option wird im Folgenden im Detail beschrieben
|
||||
|
||||
|
||||
### Bei Nutzung der Google Container Registry
|
||||
|
||||
Kubernetes hat eine native Unterstützung für die [Google Container
|
||||
Registry (GCR)](https://cloud.google.com/tools/container-registry/) wenn es auf der Google Compute
|
||||
Engine (GCE) läuft. Wenn Sie ihren Cluster auf GCE oder der Google Kubernetes Engine betreiben, genügt es einfach den vollen Image Namen zu nutzen (z.B. gcr.io/my_project/image:tag ).
|
||||
Engine (GCE) läuft. Wenn Sie ihren Cluster auf GCE oder der Google Kubernetes Engine betreiben, genügt es, einfach den vollen Image Namen zu nutzen (z.B. gcr.io/my_project/image:tag ).
|
||||
|
||||
Alle Pods in einem Cluster haben dann lesenden Zugriff auf Images in dieser Registry.
|
||||
Alle Pods in einem Cluster haben dann Lesezugriff auf Images in dieser Registry.
|
||||
|
||||
Das Kubelet authentifiziert sich bei GCR mit Nutzung des Google service Kontos der jeweiligen Instanz.
|
||||
Das Google service Konto der Instanz hat einen `https://www.googleapis.com/auth/devstorage.read_only`, so kann es vom GCR des Projektes hochladen, aber nicht herunterladen.
|
||||
Das Google Servicekonto der Instanz hat einen `https://www.googleapis.com/auth/devstorage.read_only`, so kann es vom GCR des Projektes herunter, aber nicht hochladen.
|
||||
|
||||
|
||||
### Bei Nutzung der Amazon Elastic Container Registry
|
||||
|
||||
Kubernetes eine native Unterstützung für die [Amazon Elastic Container Registry](https://aws.amazon.com/ecr/) wenn Knoten AWS EC2 Instanzen sind.
|
||||
Kubernetes bietet native Unterstützung für die [Amazon Elastic Container Registry](https://aws.amazon.com/ecr/), wenn Knoten AWS EC2 Instanzen sind.
|
||||
|
||||
Es muss einfach nur der komplette Image Name (z.B. `ACCOUNT.dkr.ecr.REGION.amazonaws.com/imagename:tag`) in der Pod - Definition genutzt werden.
|
||||
|
||||
Alle Benutzer eines Clusters die Pods erstellen dürfen können dann jedes der Images in der ECR Registry zum Ausführen von Pods nutzen.
|
||||
Alle Benutzer eines Clusters, die Pods erstellen dürfen, können dann jedes der Images in der ECR Registry zum Ausführen von Pods nutzen.
|
||||
|
||||
Das Kubelet wird periodisch ECR Zugriffsdaten herunterladen und auffrischen, es benötigt hierfür die folgenden Berechtigungen:
|
||||
|
||||
|
@ -126,12 +126,12 @@ Fehlerbehebung:
|
|||
- `provider.go:91] Refreshing cache for provider: *aws_credentials.ecrProvider`
|
||||
|
||||
### Bei Nutzung der Azure Container Registry (ACR)
|
||||
Bei Nutzung der [Azure Container Registry](https://azure.microsoft.com/en-us/services/container-registry/) können sie sich entweder als ein administrativer Nutzer, oder als ein Service Principal authentifizieren
|
||||
Bei Nutzung der [Azure Container Registry](https://azure.microsoft.com/en-us/services/container-registry/) können sie sich entweder als ein administrativer Nutzer, oder als ein Service Principal authentifizieren.
|
||||
In jedem Fall wird die Authentifizierung über die Standard - Docker Authentifizierung ausgeführt. Diese Anleitung bezieht sich auf das [azure-cli](https://github.com/azure/azure-cli) Kommandozeilenwerkzeug.
|
||||
|
||||
Sie müssen zunächst eine Registry und Authentifizierungsdaten erstellen, eine komplette Dokumentation dazu finden sie hier: [Azure container registry documentation](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-azure-cli).
|
||||
|
||||
Sobald sie ihre Container Registry erstelt haben, nutzen sie die folgenden Authentifizierungsdaten:
|
||||
Sobald sie ihre Container Registry erstellt haben, nutzen sie die folgenden Authentifizierungsdaten:
|
||||
|
||||
* `DOCKER_USER` : Service Principal oder Administratorbenutzername
|
||||
* `DOCKER_PASSWORD`: Service Principal Password oder Administratorpasswort
|
||||
|
@ -139,37 +139,37 @@ Sobald sie ihre Container Registry erstelt haben, nutzen sie die folgenden Authe
|
|||
* `DOCKER_EMAIL`: `${some-email-address}`
|
||||
|
||||
Wenn sie diese Variablen befüllt haben, können sie:
|
||||
[configure a Kubernetes Secret and use it to deploy a Pod](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod).
|
||||
[Kubernetes konfigurieren und damit einen Pod deployen](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod).
|
||||
|
||||
### Bei Nutzung der IBM Cloud Container Registry
|
||||
Die IBM Cloud Container Registry bietet eine mandantenfähige Private Image Registry die Sie nutzen können um ihre Docker Images sicher speichern und teilen zu können.
|
||||
Im Standard werden Images in ihrer Private Registry vom integrierten Schwachstellenscaner durchsucht um Sicherheitsprobleme und potentielle Schwachstellen zu finden. Benutzer können ihren IBM Cloud Account nutzen um Zugang zu ihren Images zu erhalten, oder um einen Token zu gernerieren, der Zugriff auf die Registry Namespaces erlaubt.
|
||||
Die IBM Cloud Container Registry bietet eine mandantenfähige Private Image Registry, die Sie nutzen können, um ihre Docker Images sicher zu speichern und zu teilen.
|
||||
Standardmäßig werden Images in ihrer Private Registry vom integrierten Schwachstellenscaner durchsucht, um Sicherheitsprobleme und potentielle Schwachstellen zu finden. Benutzer können ihren IBM Cloud Account nutzen, um Zugang zu ihren Images zu erhalten, oder um einen Token zu generieren, der Zugriff auf die Registry Namespaces erlaubt.
|
||||
|
||||
Um das IBM Cloud Container Registry Kommandozeilenwerkzeug zu installieren und einen Namespace für ihre Images zu erstellen, folgen sie dieser Dokumentation [Getting started with IBM Cloud Container Registry](https://cloud.ibm.com/docs/services/Registry?topic=registry-getting-started).
|
||||
|
||||
Sie können die IBM Cloud Container Registry nutzen um Container aus [IBM Cloud public images](https://cloud.ibm.com/docs/services/Registry?topic=registry-public_images) und ihren eigenen Images in den `default` Namespace ihres IBM Cloud Kubernetes Service Clusters zu deployen.
|
||||
Sie können die IBM Cloud Container Registry nutzen, um Container aus [IBM Cloud public images](https://cloud.ibm.com/docs/services/Registry?topic=registry-public_images) und ihren eigenen Images in den `default` Namespace ihres IBM Cloud Kubernetes Service Clusters zu deployen.
|
||||
Um einen Container in einen anderen Namespace, oder um ein Image aus einer anderen IBM Cloud Container Registry Region oder einem IBM Cloud account zu deployen, erstellen sie ein Kubernetes `imagePullSecret`.
|
||||
Weitere Informationen finden sie unter: [Building containers from images](https://cloud.ibm.com/docs/containers?topic=containers-images).
|
||||
|
||||
### Knoten für die Nutzung einer Private Registry konfigurieren
|
||||
|
||||
{{< note >}}
|
||||
Wenn sie auf Google Kubernetes Engine laufen gibt es schon eine `.dockercfg` auf jedem Knoten die Zugriffsdaten für ihre Google Container Registry beinhaltet. Dann kann die folgende Vorgehensweise nicht angewendet werden.
|
||||
Wenn sie Google Kubernetes Engine verwenden, gibt es schon eine `.dockercfg` auf jedem Knoten, die Zugriffsdaten für ihre Google Container Registry beinhaltet. Dann kann die folgende Vorgehensweise nicht angewendet werden.
|
||||
{{< /note >}}
|
||||
|
||||
{{< note >}}
|
||||
Wenn sie auf AWS EC2 laufen und die EC2 Container Registry (ECR) nutzen, wird das Kubelet auf jedem Knoten die ECR Zugriffsdaten verwalten und aktualisieren. Dann kann die folgende Vorgehensweise nicht angewendet werden.
|
||||
Wenn sie AWS EC2 verwenden und die EC2 Container Registry (ECR) nutzen, wird das Kubelet auf jedem Knoten die ECR Zugriffsdaten verwalten und aktualisieren. Dann kann die folgende Vorgehensweise nicht angewendet werden.
|
||||
{{< /note >}}
|
||||
|
||||
{{< note >}}
|
||||
Diese Vorgehensweise ist anwendbar wenn sie ihre Knoten - Konfiguration ändern können, sie wird nicht zuverlässig auf GCE other einem anderen Cloud - Provider funktionieren der automatisch Knoten ersetzt.
|
||||
Diese Vorgehensweise ist anwendbar, wenn sie ihre Knoten-Konfiguration ändern können; Sie wird nicht zuverlässig auf GCE oder einem anderen Cloud - Provider funktionieren, der automatisch Knoten ersetzt.
|
||||
{{< /note >}}
|
||||
|
||||
{{< note >}}
|
||||
Kubernetes unterstützt zur Zeit nur die `auths` und `HttpHeaders` Sektionen der Docker Konfiguration . Das bedeutet das die Hilfswerkzeuge (`credHelpers` ooderr `credsStore`) nicht unterstützt werden.
|
||||
Kubernetes unterstützt zurzeit nur die `auths` und `HttpHeaders` Abschnitte der Dockerkonfiguration. Das bedeutet, dass die Hilfswerkzeuge (`credHelpers` ooderr `credsStore`) nicht unterstützt werden.
|
||||
{{< /note >}}
|
||||
|
||||
Docker speichert Schlüssel für eigene Registries in der Datei `$HOME/.dockercfg` oder `$HOME/.docker/config.json`. Wenn sie die gleiche Datei in einen der unten aufgeführten Suchpfade ablegen wird Kubelet sie als Hilfswerkzeug für Zugriffsdaten nutzen wenn es Images bezieht.
|
||||
Docker speichert Schlüssel für eigene Registries entweder unter `$HOME/.dockercfg` oder `$HOME/.docker/config.json`. Wenn sie die gleiche Datei in einen der unten aufgeführten Suchpfade speichern, wird Kubelet sie als Hilfswerkzeug für Zugriffsdaten beim Beziehen von Images nutzen.
|
||||
|
||||
|
||||
* `{--root-dir:-/var/lib/kubelet}/config.json`
|
||||
|
@ -182,20 +182,21 @@ Docker speichert Schlüssel für eigene Registries in der Datei `$HOME/.dockercf
|
|||
* `/.dockercfg`
|
||||
|
||||
{{< note >}}
|
||||
Eventuell müssen sie `HOME=/root` in ihrer Umgebungsvariablendatei setzen
|
||||
Eventuell müssen sie `HOME=/root` in ihrer Umgebungsvariablendatei setzen.
|
||||
{{< /note >}}
|
||||
|
||||
Dies sind die empfohlenen Schritte um ihre Knoten für eine Nutzung einer eigenen Registry zu konfigurieren, in diesem Beispiel führen sie folgende Schritte auf ihrem Desktop/Laptop aus:
|
||||
Dies sind die empfohlenen Schritte, um ihre Knoten für eine Nutzung einer eigenen Registry zu konfigurieren.
|
||||
In diesem Beispiel führen sie folgende Schritte auf ihrem Desktop/Laptop aus:
|
||||
|
||||
1. Führen sie `docker login [server]` für jeden Satz ihrer Zugriffsdaten aus. Dies aktualisiert `$HOME/.docker/config.json`.
|
||||
2. Prüfen Sie `$HOME/.docker/config.json` in einem Editor darauf ob dort nur Zugriffsdaten enthalten sind die Sie nutzen möchten.
|
||||
2. Prüfen Sie `$HOME/.docker/config.json` in einem Editor darauf, ob dort nur Zugriffsdaten enthalten sind, die Sie nutzen möchten.
|
||||
3. Erhalten sie eine Liste ihrer Knoten:
|
||||
- Wenn sie die Namen benötigen: `nodes=$(kubectl get nodes -o jsonpath='{range.items[*].metadata}{.name} {end}')`
|
||||
- Wenn sie die IP - Adressen benötigen: `nodes=$(kubectl get nodes -o jsonpath='{range .items[*].status.addresses[?(@.type=="ExternalIP")]}{.address} {end}')`
|
||||
4. Kopieren sie ihre lokale `.docker/config.json` in einen der oben genannten Suchpfade.
|
||||
- Zum Beispiel: `for n in $nodes; do scp ~/.docker/config.json root@$n:/var/lib/kubelet/config.json; done`
|
||||
|
||||
Prüfen durch das Erstellen eines Pods der ein eigenes Image nutzt, z.B.:
|
||||
Prüfen durch das Erstellen eines Pods, der ein eigenes Image nutzt, z.B.:
|
||||
|
||||
```yaml
|
||||
kubectl apply -f - <<EOF
|
||||
|
@ -212,7 +213,7 @@ spec:
|
|||
EOF
|
||||
pod/private-image-test-1 created
|
||||
```
|
||||
Wenn alles funktioniert sollten sie nach einigen Momenten folgendes sehen:
|
||||
Wenn alles funktioniert, sollten sie nach einigen Momenten folgendes sehen:
|
||||
|
||||
```shell
|
||||
kubectl logs private-image-test-1
|
||||
|
@ -225,27 +226,27 @@ kubectl describe pods/private-image-test-1 | grep "Failed"
|
|||
Fri, 26 Jun 2015 15:36:13 -0700 Fri, 26 Jun 2015 15:39:13 -0700 19 {kubelet node-i2hq} spec.containers{uses-private-image} failed Failed to pull image "user/privaterepo:v1": Error: image user/privaterepo:v1 not found
|
||||
```
|
||||
|
||||
Sie müssen sich darum kümmern das alle Knoten im Cluster die gleiche `.docker/config.json` haben, anderenfalls werden Pods auf einigen Knoten starten, auf anderen jedoch nicht.
|
||||
Wenn sie zum Beispiel Knoten automatisch Skalieren lassen, sollte dann jedes Instanztemplate die `.docker/config.json` beinhalten, oder ein Laufwerk einhängen die diese beinhaltet.
|
||||
Sie müssen sich darum kümmern, dass alle Knoten im Cluster die gleiche `.docker/config.json` haben, andernfalls werden Pods auf einigen Knoten starten, auf anderen jedoch nicht.
|
||||
Wenn sie zum Beispiel Knoten automatisch skalieren lassen, sollte dann jedes Instanztemplate die `.docker/config.json` beinhalten, oder ein Laufwerk einhängen, das diese beinhaltet.
|
||||
|
||||
Alle Pods haben Lesezugriff auf jedes Image in ihrer eigenen Registry sobald die Registry - Schlüssel zur `.docker/config.json` hinzugefügt wurden.
|
||||
Alle Pods haben Lesezugriff auf jedes Image in ihrer eigenen Registry, sobald die Registry - Schlüssel zur `.docker/config.json` hinzugefügt wurden.
|
||||
|
||||
### Im Voraus heruntergeladene Images
|
||||
|
||||
{{< note >}}
|
||||
Wenn sie auf Google Kubernetes Engine laufen gibt es schon eine `.dockercfg` auf jedem Knoten die Zugriffsdaten für ihre Google Container Registry beinhaltet. Dann kann die folgende Vorgehensweise nicht angewendet werden.
|
||||
Wenn sie Google Kubernetes Engine verwenden, gibt es schon eine `.dockercfg` auf jedem Knoten die Zugriffsdaten für ihre Google Container Registry beinhaltet. Dann kann die folgende Vorgehensweise nicht angewendet werden.
|
||||
{{< /note >}}
|
||||
|
||||
{{< note >}}
|
||||
Diese Vorgehensweise ist anwendbar wenn sie ihre Knoten - Konfiguration ändern können, sie wird nicht zuverlässig auf GCE other einem anderen Cloud - Provider funktionieren der automatisch Knoten ersetzt.
|
||||
Diese Vorgehensweise ist anwendbar, wenn sie ihre Knoten-Konfiguration ändern können; Sie wird nicht zuverlässig auf GCE oder einem anderen Cloud - Provider funktionieren, der automatisch Knoten ersetzt.
|
||||
{{< /note >}}
|
||||
|
||||
Im Standard wird das Kubelet versuchen jedes Image von der spezifizierten Registry herunterzuladen.
|
||||
Falls jedoch die `imagePullPolicy` Eigenschaft der Containers auf `IfNotPresent` oder `Never` gesetzt wurde, wird ein lokales Image genutzt (präferiert oder exklusiv, je nach dem).
|
||||
Standardmäßig wird das Kubelet versuchen, jedes Image von der spezifizierten Registry herunterzuladen.
|
||||
Falls jedoch die `imagePullPolicy` Eigenschaft der Containers auf `IfNotPresent` oder `Never` gesetzt wurde, wird ein lokales Image genutzt (präferiert oder exklusiv, jenachdem).
|
||||
|
||||
Wenn Sie sich auf im Voraus heruntergeladene Images als Ersatz für eine Registry - Authentifizierung verlassen möchten, müssen sie sicherstellen das alle Knoten die gleichen im voraus heruntergeladenen Images aufweisen.
|
||||
Wenn Sie sich auf im Voraus heruntergeladene Images als Ersatz für eine Registry - Authentifizierung verlassen möchten, müssen sie sicherstellen, dass alle Knoten die gleichen, im Voraus heruntergeladenen Images aufweisen.
|
||||
|
||||
Diese Medthode kann dazu genutzt werden bestimmte Images aus Geschwindigkeitsgründen im Voraus zu laden, oder als Alternative zur Authentifizierung an einer eigenen Registry zu nutzen.
|
||||
Diese Medthode kann dazu genutzt werden, bestimmte Images aus Geschwindigkeitsgründen im Voraus zu laden, oder als Alternative zur Authentifizierung an einer eigenen Registry zu nutzen.
|
||||
|
||||
Alle Pods haben Leserechte auf alle im Voraus geladenen Images.
|
||||
|
||||
|
@ -259,24 +260,24 @@ Kubernetes unterstützt die Spezifikation von Registrierungsschlüsseln für ein
|
|||
|
||||
#### Erstellung eines Secrets mit einer Docker Konfiguration
|
||||
|
||||
Führen sie foldenen Befehl mit Ersetzung der groß geschriebenen Werte aus:
|
||||
Führen sie folgenden Befehl mit Ersetzung der groß geschriebenen Werte aus:
|
||||
|
||||
```shell
|
||||
kubectl create secret docker-registry <name> --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
|
||||
```
|
||||
|
||||
Wenn sie bereits eine Datei mit Docker Zugriffsdaten haben, könenn sie die Zugriffsdaten als ein Kubernetes Secret importieren:
|
||||
Wenn Sie bereits eine Datei mit Docker-Zugriffsdaten haben, können Sie die Zugriffsdaten als ein Kubernetes Secret importieren:
|
||||
[Create a Secret based on existing Docker credentials](/docs/tasks/configure-pod-container/pull-image-private-registry/#registry-secret-existing-credentials) beschreibt die Erstellung.
|
||||
Dies ist insbesondere dann sinnvoll wenn sie mehrere eigene Container Registries nutzen, da `kubectl create secret docker-registry` ein Secret erstellt das nur mit einer einzelnen eigenen Registry funktioniert.
|
||||
Dies ist insbesondere dann sinnvoll, wenn sie mehrere eigene Container Registries nutzen, da `kubectl create secret docker-registry` ein Secret erstellt, das nur mit einer einzelnen eigenen Registry funktioniert.
|
||||
|
||||
{{< note >}}
|
||||
Pods können nur eigene Image Pull Secret in ihrem eigenen Namespace referenzieren, somit muss dieser Prozess jedes mal einzeln für je Namespace angewendet werden.
|
||||
Pods können nur eigene Image Pull Secret in ihrem eigenen Namespace referenzieren, somit muss dieser Prozess jedes mal einzeln für jeden Namespace angewendet werden.
|
||||
|
||||
{{< /note >}}
|
||||
|
||||
#### Referenzierung eines imagePullSecrets bei einem Pod
|
||||
|
||||
Nun können sie Pods erstellen die dieses Secret referenzieren indem sie eine `imagePullSecrets` Sektion zu ihrer Pod - Definition hinzufügen.
|
||||
Nun können Sie Pods erstellen, die dieses Secret referenzieren, indem Sie einen Aschnitt `imagePullSecrets` zu ihrer Pod - Definition hinzufügen.
|
||||
|
||||
```shell
|
||||
cat <<EOF > pod.yaml
|
||||
|
@ -299,9 +300,9 @@ resources:
|
|||
EOF
|
||||
```
|
||||
|
||||
Dies muss für jeden Pod getan werden der eine eigene Registry nutzt.
|
||||
Dies muss für jeden Pod getan werden, der eine eigene Registry nutzt.
|
||||
|
||||
Die Erstellung dieser Sektion kann jedoch automatisiert werden indem man imagePullSecrets einer serviceAccount](/docs/user-guide/service-accounts) Ressource hinzufügt.
|
||||
Die Erstellung dieser Sektion kann jedoch automatisiert werden, indem man imagePullSecrets einer [serviceAccount](/docs/user-guide/service-accounts) Ressource hinzufügt.
|
||||
[Add ImagePullSecrets to a Service Account](/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account) bietet detaillierte Anweisungen hierzu.
|
||||
|
||||
Sie können dies in Verbindung mit einer auf jedem Knoten genutzten `.docker/config.json` benutzen, die Zugriffsdaten werden dann zusammengeführt. Dieser Vorgehensweise wird in der Google Kubernetes Engine funktionieren.
|
||||
|
@ -333,7 +334,7 @@ Es gibt eine Anzahl an Lösungen um eigene Registries zu konfigurieren, hier sin
|
|||
- Generieren die Registry - Zugriffsdaten für jeden Mandanten, abgelegt in einem Secret das in jedem Mandanten - Namespace vorhanden ist.
|
||||
- Der Mandant fügt dieses Sercret zu den imagePullSecrets in jedem seiner Namespace hinzu.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
Falls die Zugriff auf mehrere Registries benötigen, können sie ein Secret für jede Registry erstellen, Kubelet wird jedwede `imagePullSecrets` in einer einzelnen `.docker/config.json` zusammenfassen.
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
---
|
||||
title: Konzept Dokumentations-Vorlage
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
toc_hide: true
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
{{< note >}}
|
||||
Stellen Sie auch sicher [einen Eintrag im Inhaltsverzeichnis](/docs/home/contribute/write-new-topic/#creating-an-entry-in-the-table-of-contents) für Ihr neues Dokument zu erstellen.
|
||||
|
@ -12,9 +12,9 @@ Stellen Sie auch sicher [einen Eintrag im Inhaltsverzeichnis](/docs/home/contrib
|
|||
|
||||
Diese Seite erklärt ...
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Verstehen ...
|
||||
|
||||
|
@ -24,15 +24,16 @@ Kubernetes bietet ...
|
|||
|
||||
Benutzen Sie ...
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
|
||||
**[Optionaler Bereich]**
|
||||
|
||||
* Lernen Sie mehr über [ein neues Thema schreiben](/docs/home/contribute/write-new-topic/).
|
||||
* Besuchen Sie [Seitenvorlagen verwenden - Konzeptvorlage](/docs/home/contribute/page-templates/#concept_template) wie Sie diese Vorlage verwenden.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
---
|
||||
title: Kubernetes Komponenten
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
weight: 20
|
||||
card:
|
||||
name: concepts
|
||||
weight: 20
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
In diesem Dokument werden die verschiedenen binären Komponenten beschrieben, die zur Bereitstellung eines funktionsfähigen Kubernetes-Clusters erforderlich sind.
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
## Master-Komponenten
|
||||
|
||||
Master-Komponenten stellen die Steuerungsebene des Clusters bereit. Master-Komponenten treffen globale Entscheidungen über den Cluster (z. B. Zeitplanung) und das Erkennen und Reagieren auf Clusterereignisse (Starten eines neuen Pods, wenn das `replicas`-Feld eines Replikationscontrollers nicht zufriedenstellend ist).
|
||||
|
@ -107,6 +107,6 @@ Von Kubernetes gestartete Container schließen diesen DNS-Server automatisch in
|
|||
|
||||
Ein [Cluster-level logging](/docs/concepts/cluster-administration/logging/) Mechanismus ist für das Speichern von Containerprotokollen in einem zentralen Protokollspeicher mit Such- / Browsing-Schnittstelle verantwortlich.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
---
|
||||
title: Was ist Kubernetes?
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
weight: 10
|
||||
card:
|
||||
name: concepts
|
||||
weight: 10
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
Diese Seite ist eine Übersicht über Kubernetes.
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
Kubernetes ist eine portable, erweiterbare Open-Source-Plattform zur Verwaltung von
|
||||
containerisierten Arbeitslasten und Services, die sowohl die deklarative Konfiguration als auch die Automatisierung erleichtert.
|
||||
|
@ -160,11 +160,12 @@ Der Name **Kubernetes** stammt aus dem Griechischen, bedeutet *Steuermann* oder
|
|||
[cybernetic](http://www.etymonline.com/index.php?term=cybernetics). *K8s*
|
||||
ist eine Abkürzung, die durch Ersetzen der 8 Buchstaben "ubernete" mit "8" abgeleitet wird.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
* [Bereit loszulegen](/docs/setup/)?
|
||||
* Weitere Einzelheiten finden Sie in der [Kubernetes Dokumentation](/docs/home/).
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
---
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
title: Zur Kubernets-Dokumentation beitragen
|
||||
linktitle: Mitmachen
|
||||
main_menu: true
|
||||
weight: 80
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
Wenn Sie an der Dokumentation oder der Website von Kubernetes mitwirken möchten, freuen wir uns über Ihre Hilfe!
|
||||
Jeder kann seinen Beitrag leisten, unabhängig davon ob Sie neu im Projekt sind oder schon lange dabei sind, und ob Sie sich als
|
||||
|
@ -15,7 +15,7 @@ Entwickler, Endbenutzer oder einfach jemanden, der es einfach nicht aushält, Ti
|
|||
Weitere Möglichkeiten, sich in der Kubernetes-Community zu engagieren oder mehr über uns zu erfahren, finden Sie auf der [Kubernetes-Community-Seite](/community/).
|
||||
Informationen zum Handbuch zur Dokumentation von Kubernetes finden Sie im [Gestaltungshandbuch](/docs/contribute/style/style-guide/).
|
||||
|
||||
{{% capture body %}}
|
||||
<!-- body -->
|
||||
|
||||
## Arten von Mitwirkenden
|
||||
|
||||
|
@ -59,4 +59,4 @@ Dies ist keine vollständige Liste von Möglichkeiten, wie Sie zur Kubernetes-Do
|
|||
- Verbesserungsvorschläge für Dokumentprüfungen vorschlagen
|
||||
- Vorschläge für Verbesserungen der Kubernetes-Website oder anderer Tools
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
|
|
@ -0,0 +1,290 @@
|
|||
---
|
||||
title: Lokalisierung der Kubernetes Dokumentation
|
||||
content_type: concept
|
||||
weight: 50
|
||||
card:
|
||||
name: mitarbeiten
|
||||
weight: 50
|
||||
title: Übersetzen der Dokumentation
|
||||
---
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
Diese Seite zeigt dir wie die Dokumentation für verschiedene Sprachen [lokalisiert](https://blog.mozilla.org/l10n/2011/12/14/i18n-vs-l10n-whats-the-diff/) wird.
|
||||
|
||||
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Erste Schritte
|
||||
|
||||
Da Mitwirkende nicht ihren eigenen Pull Request freigeben können, brauchst du mindestens zwei Mitwirkende um mit der Lokalisierung anfangen zu können.
|
||||
|
||||
Alle Lokalisierungsteams müssen sich mit ihren eigenen Ressourcen selbst tragen. Die Kubernetes-Website ist gerne bereit, deine Arbeit zu beherbergen, aber es liegt an dir, sie zu übersetzen.
|
||||
|
||||
### Finden deinen Zwei-Buchstaben-Sprachcode
|
||||
|
||||
Rufe den [ISO 639-1 Standard](https://www.loc.gov/standards/iso639-2/php/code_list.php) auf und finde deinen Zwei-Buchstaben-Ländercode zur Lokalisierung. Zum Beispiel ist der Zwei-Buchstaben-Code für Korea `ko`.
|
||||
|
||||
### Duplizieren und klonen des Repositories
|
||||
|
||||
Als erstes [erstells du dir deine eigenes Duplikat](/docs/contribute/new-content/new-content/#fork-the-repo) vom [kubernetes/website] Repository.
|
||||
|
||||
Dann klonst du das Duplikat und `cd` hinein:
|
||||
|
||||
```shell
|
||||
git clone https://github.com/<username>/website
|
||||
cd website
|
||||
```
|
||||
|
||||
### Eröffne ein Pull Request
|
||||
|
||||
Als nächstes [eröffnest du einen Pull Request](/docs/contribute/new-content/open-a-pr/#open-a-pr) (PR) um eine Lokalisierung zum `kubernetes/website` Repository hinzuzufügen.
|
||||
|
||||
Der PR muss die [minimalen Inhaltsanforderungen](#mindestanforderungen) erfüllen bevor dieser genehmigt werden kann.
|
||||
|
||||
Wie der PR für eine neue Lokalisierung aussieht kannst du dir an dem PR für die [Französische Dokumentation](https://github.com/kubernetes/website/pull/12548) ansehen.
|
||||
|
||||
### Trete der Kubernetes GitHub Organisation bei
|
||||
|
||||
Sobald du eine Lokalisierungs-PR eröffnet hast, kannst du Mitglied der Kubernetes GitHub Organisation werden. Jede Person im Team muss einen eigenen [Antrag auf Mitgliedschaft in der Organisation](https://github.com/kubernetes/org/issues/new/choose) im `kubernetes/org`-Repository erstellen.
|
||||
|
||||
### Lokalisierungs-Team in GitHub hinzufügen
|
||||
|
||||
Im nächsten Schritt musst du dein Kubernetes Lokalisierungs-Team in die [`sig-docs/teams.yaml`](https://github.com/kubernetes/org/blob/master/config/kubernetes/sig-docs/teams.yaml) eintragen.
|
||||
|
||||
Der PR des [Spanischen Lokalisierungs-Teams](https://github.com/kubernetes/org/pull/685) kann dir hierbei eine Hilfestellung sein.
|
||||
|
||||
Mitglieder der `@kubernetes/sig-docs-**-owners` können nur PRs freigeben die innerhalb deines Lokalisierungs-Ordners Änderungen vorgenommen haben: `/content/**/`.
|
||||
|
||||
Für jede Lokalisierung automatisiert das Team `@kubernetes/sig-docs-**-reviews` die Review-Zuweisung für neue PRs.
|
||||
|
||||
Mitglieder von `@kubernetes/website-maintainers` können neue Entwicklungszweige schaffen, um die Übersetzungsarbeiten zu koordinieren.
|
||||
|
||||
Mitglieder von `@kubernetes/website-milestone-maintainers` können den Befehl `/milestone` [Prow Kommando](https://prow.k8s.io/command-help) verwenden, um Themen oder PRs einen Meilenstein zuzuweisen.
|
||||
|
||||
### Workflow konfigurieren
|
||||
|
||||
Als nächstes fügst du ein GitHub-Label für deine Lokalisierung im `kubernetes/test-infra`-Repository hinzu. Mit einem Label kannst du Aufgaben filtern und Anfragen für deine spezifische Sprache abrufen.
|
||||
|
||||
Schau dir den PR zum Hinzufügen der Labels für die [Italienischen Sprachen-Labels](https://github.com/kubernetes/test-infra/pull/11316 an.
|
||||
|
||||
|
||||
### Finde eine Gemeinschaft
|
||||
|
||||
Lasse die Kubernetes SIG Docs wissen, dass du an der Erstellung einer Lokalisierung interessiert bist! Trete dem [SIG Docs Slack-Kanal](https://kubernetes.slack.com/messages/C1J0BPD2M/) bei. Andere Lokalisierungsteams helfen dir gerne beim Einstieg und beantworten deine Fragen.
|
||||
|
||||
Du kannst auch einen Slack-Kanal für deine Lokalisierung im `kubernetes/community`-Repository erstellen. Ein Beispiel für das Hinzufügen eines Slack-Kanals findest du im PR für [Kanäle für Indonesisch und Portugiesisch hinzufügen](https://github.com/kubernetes/community/pull/3605).
|
||||
|
||||
|
||||
## Mindestanforderungen
|
||||
|
||||
### Ändere die Website-Konfiguration
|
||||
|
||||
Die Kubernetes-Website verwendet Hugo als Web-Framework. Die Hugo-Konfiguration der Website befindet sich in der Datei [`config.toml`](https://github.com/kubernetes/website/tree/master/config.toml). Um eine neue Lokalisierung zu unterstützen, musst du die Datei `config.toml` modifizieren.
|
||||
|
||||
Dazu fügst du einen neuen Block für die neue Sprache unter den bereits existierenden `[languages]` Block in das `config.toml` ein, wie folgendes Beispiel zeigt:
|
||||
|
||||
```toml
|
||||
[languages.de]
|
||||
title = "Kubernetes"
|
||||
description = "Produktionsreife Container-Verwaltung"
|
||||
languageName = "Deutsch"
|
||||
contentDir = "content/de"
|
||||
weight = 3
|
||||
```
|
||||
|
||||
Wenn du deinem Block einen Parameter `weight` zuweist, suche den Sprachblock mit dem höchsten Gewicht und addiere 1 zu diesem Wert.
|
||||
|
||||
Weitere Informationen zu Hugos Multilingualen Support findest du unter "[Multilingual Mode](https://gohugo.io/content-management/multilingual/)" auf in der Hugo Dokumentation.
|
||||
|
||||
### Neuen Lokalisierungsordner erstellen
|
||||
|
||||
Füge eine sprachspezifisches Unterverzeichnis zum Ordner [`content`](https://github.com/kubernetes/website/tree/master/content) im Repository hinzu. Der Zwei-Buchstaben-Code für Deutsch ist zum Beispiel `de`:
|
||||
|
||||
```shell
|
||||
mkdir content/de
|
||||
```
|
||||
|
||||
### Lokalisiere den Verhaltenscodex
|
||||
Öffne einen PR gegen das [`cncf/foundation`](https://github.com/cncf/foundation/tree/master/code-of-conduct-languages) Repository, um den Verhaltenskodex in deiner Sprache hinzuzufügen.
|
||||
|
||||
### Lokalisierungs README Datei hinzufügen
|
||||
|
||||
Um andere Lokalisierungsmitwirkende anzuleiten, füge eine neue [`README-**.md`](https://help.github.com/articles/about-readmes/) auf der obersten Ebene von k/website hinzu, wobei `**` der aus zwei Buchstaben bestehende Sprachcode ist. Eine deutsche README-Datei wäre zum Beispiel `README-de.md`.
|
||||
|
||||
Gebe den Lokalisierungsmitwirkende in der lokalisierten `README-**.md`-Datei Anleitung zum Mitwirken. Füge dieselben Informationen ein, die auch in `README.md` enthalten sind, sowie:
|
||||
|
||||
- Eine Anlaufstelle für das Lokalisierungsprojekt
|
||||
- Alle für die Lokalisierung spezifischen Informationen
|
||||
|
||||
Nachdem du das lokalisierte README erstellt hast, füge der Datei einen Link aus der englischen Hauptdatei `README.md` hinzu und gebe die Kontaktinformationen auf Englisch an. Du kannst eine GitHub-ID, eine E-Mail-Adresse, [Slack-Kanal](https://slack.com/) oder eine andere Kontaktmethode angeben. Du musst auch einen Link zu deinem lokalisierten Verhaltenskodex der Gemeinschaft angeben.
|
||||
|
||||
### Richte eine OWNERS Datei ein
|
||||
|
||||
Um die Rollen der einzelnen an der Lokalisierung beteiligten Benutzer festzulegen, erstelle eine `OWNERS`-Datei innerhalb des sprachspezifischen Unterverzeichnisses mit:
|
||||
|
||||
- **reviewers**: Eine Liste von kubernetes-Teams mit Gutachter-Rollen, in diesem Fall das `sig-docs-**-reviews` Team, das in [Lokalisierungsteam in GitHub hinzufügen](#lokalisierungs-team-in-github-hinzufügen) erstellt wurde.
|
||||
- **approvers**: Eine Liste der Kubernetes-Teams mit der Rolle des Genehmigers, in diesem Fall das `sig-docs-**-owners` Team, das in [Lokalisierungsteam in GitHub hinzufügen](#lokalisierungs-team-in-github-hinzufügen) erstellt wurde.
|
||||
- **labels**: Eine Liste von GitHub-Labels, die automatisch auf einen PR angewendet werden sollen, in diesem Fall das Sprachlabel, das unter [Workflow konfigurieren](#workflow-konfigurieren) erstellt wurde.
|
||||
|
||||
Weitere Informationen über die Datei `OWNERS` findest du unter [go.k8s.io/owners](https://go.k8s.io/owners).
|
||||
|
||||
Die Datei [Spanish OWNERS file](https://git.k8s.io/website/content/es/OWNERS), mit dem Sprachcode `es`, sieht wie folgt aus:
|
||||
|
||||
```yaml
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
# This is the localization project for Spanish.
|
||||
# Teams and members are visible at https://github.com/orgs/kubernetes/teams.
|
||||
|
||||
reviewers:
|
||||
- sig-docs-es-reviews
|
||||
|
||||
approvers:
|
||||
- sig-docs-es-owners
|
||||
|
||||
labels:
|
||||
- language/es
|
||||
```
|
||||
Nachdem du die sprachspezifische Datei `OWNERS` hinzugefügt hast, aktualisiere die root Datei [`OWNERS_ALIASES`](https://git.k8s.io/website/OWNERS_ALIASES) mit den neuen Kubernetes-Teams für die Lokalisierung, `sig-docs-**-owners` und `sig-docs-**-reviews`.
|
||||
|
||||
Füge für jedes Team die Liste der unter [Ihr Lokalisierungsteam in GitHub hinzufügen](#lokalisierungs-team-in-github-hinzufügen) angeforderten GitHub-Benutzer in alphabetischer Reihenfolge hinzu.
|
||||
|
||||
```diff
|
||||
--- a/OWNERS_ALIASES
|
||||
+++ b/OWNERS_ALIASES
|
||||
@@ -48,6 +48,14 @@ aliases:
|
||||
- stewart-yu
|
||||
- xiangpengzhao
|
||||
- zhangxiaoyu-zidif
|
||||
+ sig-docs-es-owners: # Admins for Spanish content
|
||||
+ - alexbrand
|
||||
+ - raelga
|
||||
+ sig-docs-es-reviews: # PR reviews for Spanish content
|
||||
+ - alexbrand
|
||||
+ - electrocucaracha
|
||||
+ - glo-pena
|
||||
+ - raelga
|
||||
sig-docs-fr-owners: # Admins for French content
|
||||
- perriea
|
||||
- remyleone
|
||||
```
|
||||
|
||||
## Inhalte übersetzen
|
||||
|
||||
Die Lokalisierung *aller* Dokumentationen des Kubernetes ist eine enorme Aufgabe. Es ist in Ordnung, klein anzufangen und mit der Zeit zu erweitern.
|
||||
|
||||
Alle Lokalisierungen müssen folgende Inhalte enthalten:
|
||||
|
||||
Beschreibung | URLs
|
||||
-----|-----
|
||||
Startseite | [Alle Überschriften und Untertitel URLs](/docs/home/)
|
||||
Einrichtung | [Alle Überschriften und Untertitel URLs](/docs/setup/)
|
||||
Tutorials | [Kubernetes Grundlagen](/docs/tutorials/kubernetes-basics/), [Hello Minikube](/docs/tutorials/stateless-application/hello-minikube/)
|
||||
Site strings | [Alle Website-Zeichenfolgen in einer neuen lokalisierten TOML-Datei](https://github.com/kubernetes/website/tree/master/i18n)
|
||||
|
||||
Übersetzte Dokumente müssen sich in ihrem eigenen Unterverzeichnis `content/**/` befinden, aber ansonsten dem gleichen URL-Pfad wie die englische Quelle folgen. Um z.B. das Tutorial [Kubernetes Grundlagen](/docs/tutorials/kubernetes-basics/) für die Übersetzung ins Deutsche vorzubereiten, erstelle einen Unterordner unter dem Ordner `content/de/` und kopiere die englische Quelle:
|
||||
|
||||
```shell
|
||||
mkdir -p content/de/docs/tutorials
|
||||
cp content/en/docs/tutorials/kubernetes-basics.md content/de/docs/tutorials/kubernetes-basics.md
|
||||
```
|
||||
|
||||
Übersetzungswerkzeuge können den Übersetzungsprozess beschleunigen. Einige Redakteure bieten beispielsweise Plugins zur schnellen Übersetzung von Text an.
|
||||
|
||||
|
||||
{{< caution >}}
|
||||
Maschinelle Übersetzung allein reicht nicht aus. Die Lokalisierung erfordert eine umfassende menschliche Überprüfung, um Mindestqualitätsstandards zu erfüllen.
|
||||
{{< /caution >}}
|
||||
|
||||
Um die Genauigkeit in Grammatik und Bedeutung zu gewährleisten, sollten die Mitglieder deines Lokalisierungsteams alle maschinell erstellten Übersetzungen vor der Veröffentlichung sorgfältig überprüfen.
|
||||
|
||||
### Quelldaten
|
||||
|
||||
Lokalisierungen müssen auf den englischen Dateien der neuesten Version basieren, {{< latest-version >}}.
|
||||
|
||||
Um die Quelldatei für das neueste Release führe folgende Schritte durch:
|
||||
|
||||
1. Navigiere zum Repository der Website Kubernetes unter https://github.com/kubernetes/website.
|
||||
2. Wähle den `release-1.X`-Zweig für die aktuellste Version.
|
||||
|
||||
Die neueste Version ist {{< latest-version >}}, so dass der neueste Versionszweig [`{{< release-branch >}}`](https://github.com/kubernetes/website/tree/{{< release-branch >}}) ist.
|
||||
|
||||
### Seitenverlinkung in der Internationalisierung
|
||||
|
||||
Lokalisierungen müssen den Inhalt von [`i18n/de.toml`](https://github.com/kubernetes/website/blob/master/i18n/en.toml) in einer neuen sprachspezifischen Datei enthalten. Als Beispiel: `i18n/de.toml`.
|
||||
|
||||
Füge eine neue Lokalisierungsdatei zu `i18n/` hinzu. Zum Beispiel mit Deutsch (`de`):
|
||||
|
||||
```shell
|
||||
cp i18n/en.toml i18n/de.toml
|
||||
```
|
||||
|
||||
Übersetze dann den Wert jeder Zeichenfolge:
|
||||
|
||||
```TOML
|
||||
[docs_label_i_am]
|
||||
other = "ICH BIN..."
|
||||
```
|
||||
Durch die Lokalisierung von Website-Zeichenfolgen kannst du Website-weiten Text und Funktionen anpassen: z. B. den gesetzlichen Copyright-Text in der Fußzeile auf jeder Seite.
|
||||
|
||||
### Sprachspezifischer Styleguide und Glossar
|
||||
|
||||
Einige Sprachteams haben ihren eigenen sprachspezifischen Styleguide und ihr eigenes Glossar. Siehe zum Beispiel den [Leitfaden zur koreanischen Lokalisierung](/ko/docs/contribute/localization_ko/).
|
||||
|
||||
## Branching Strategie
|
||||
|
||||
Da Lokalisierungsprojekte in hohem Maße gemeinschaftliche Bemühungen sind, ermutigen wir Teams, in gemeinsamen Entwicklungszweigen zu arbeiten.
|
||||
|
||||
In einem Entwicklungszweig zusammenzuarbeiten:
|
||||
|
||||
1. Ein Teammitglied von [@kubernetes/website-maintainers](https://github.com/orgs/kubernetes/teams/website-maintainers) eröffnet einen Entwicklungszweig aus einem Quellzweig auf https://github.com/kubernetes/website.
|
||||
|
||||
Deine Genehmiger sind dem `@kubernetes/website-maintainers`-Team beigetreten, als du [dein Lokalisierungsteam](#lokalisierungs-team-in-github-hinzufügen) zum Repository [`kubernetes/org`](https://github.com/kubernetes/org) hinzugefügt hast.
|
||||
|
||||
Wir empfehlen das folgende Zweigbenennungsschema:
|
||||
|
||||
`dev-<Quellversion>-<Sprachcode>.<Team-Meilenstein>`
|
||||
|
||||
Beispielsweise öffnet ein Genehmigender in einem deutschen Lokalisierungsteam den Entwicklungszweig `dev-1.12-de.1` direkt gegen das k/website-Repository, basierend auf dem Quellzweig für Kubernetes v1.12.
|
||||
|
||||
2. Einzelne Mitwirkende öffnen Feature-Zweige, die auf dem Entwicklungszweig basieren.
|
||||
|
||||
Zum Beispiel öffnet ein deutscher Mitwirkende eine Pull-Anfrage mit Änderungen an `kubernetes:dev-1.12-de.1` von `Benutzername:lokaler-Zweig-Name`.
|
||||
|
||||
3. Genehmiger Überprüfen und führen die Feature-Zweigen in den Entwicklungszweig zusammen.
|
||||
|
||||
4. In regelmäßigen Abständen führt ein Genehmiger den Entwicklungszweig mit seinem Ursprungszweig zusammen, indem er eine neue Pull-Anfrage eröffnet und genehmigt. Achtet darauf, die Commits zusammenzuführen (squash), bevor die Pull-Anfrage genehmigt wird.
|
||||
|
||||
Wiederhole die Schritte 1-4 nach Bedarf, bis die Lokalisierung abgeschlossen ist. Zum Beispiel würden nachfolgende deutsche Entwicklungszweige sein: `dev-1.12-de.2`, `dev-1.12-de.3`, usw.
|
||||
|
||||
Die Teams müssen den lokalisierten Inhalt in demselben Versionszweig zusammenführen, aus dem der Inhalt stammt. Beispielsweise muss ein Entwicklungszweig, der von {{< release-branch >}} ausgeht, auf {{{{< release-branch >}}} basieren.
|
||||
|
||||
Ein Genehmiger muss einen Entwicklungszweig aufrechterhalten, indem er seinen Quellzweig auf dem aktuellen Stand hält und Merge-Konflikte auflöst. Je länger ein Entwicklungszweig geöffnet bleibt, desto mehr Wartung erfordert er in der Regel. Ziehe in Betracht, regelmäßig Entwicklungszweige zusammenzuführen und neue zu eröffnen, anstatt einen extrem lang laufenden Entwicklungszweig zu unterhalten.
|
||||
|
||||
Zu Beginn jedes Team-Meilensteins ist es hilfreich, ein Problem [Vergleich der Upstream-Änderungen](https://github.com/kubernetes/website/blob/master/scripts/upstream_changes.py) zwischen dem vorherigen Entwicklungszweig und dem aktuellen Entwicklungszweig zu öffnen.
|
||||
|
||||
Während nur Genehmiger einen neuen Entwicklungszweig eröffnen und Pull-Anfragen zusammenführen können, kann jeder eine Pull-Anfrage für einen neuen Entwicklungszweig eröffnen. Es sind keine besonderen Genehmigungen erforderlich.
|
||||
|
||||
Weitere Informationen über das Arbeiten von Forks oder direkt vom Repository aus findest du unter ["fork and clone the repo"](#duplizieren-und-klonen-des-repositories).
|
||||
|
||||
## Am Upstream Mitwirken
|
||||
|
||||
SIG Docs begrüßt Upstream Beiträge, also auf das englische Original, und Korrekturen an der englischen Quelle.
|
||||
|
||||
## Unterstütze bereits bestehende Lokalisierungen
|
||||
|
||||
Du kannst auch dazu beitragen, Inhalte zu einer bestehenden Lokalisierung hinzuzufügen oder zu verbessern. Trete dem [Slack-Kanal](https://kubernetes.slack.com/messages/C1J0BPD2M/) für die Lokalisierung bei und beginne mit der Eröffnung von PRs, um zu helfen. Bitte beschränke deine Pull-Anfragen auf eine einzige Lokalisierung, da Pull-Anfragen, die Inhalte in mehreren Lokalisierungen ändern, schwer zu überprüfen sein könnten.
|
||||
|
||||
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
|
||||
Sobald eine Lokalisierung die Anforderungen an den Arbeitsablauf und die Mindestausgabe erfüllt, wird SIG docs:
|
||||
|
||||
- Die Sprachauswahl auf der Website aktivieren
|
||||
- Die Verfügbarkeit der Lokalisierung über die Kanäle der [Cloud Native Computing Foundation](https://www.cncf.io/about/) (CNCF), einschließlich des [Kubernetes Blogs](https://kubernetes.io/blog/) veröffentlichen.
|
||||
|
||||
|
|
@ -1,20 +1,20 @@
|
|||
---
|
||||
title: Unterstützte Versionen der Kubernetes-Dokumentation
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
card:
|
||||
name: about
|
||||
weight: 10
|
||||
title: Unterstützte Versionen der Dokumentation
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
Diese Website enthält Dokumentation für die aktuelle Version von Kubernetes
|
||||
und die vier vorherigen Versionen von Kubernetes.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Aktuelle Version
|
||||
|
||||
|
@ -25,6 +25,6 @@ Die aktuelle Version ist
|
|||
|
||||
{{< versions-other >}}
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -5,16 +5,16 @@ approvers:
|
|||
linkTitle: "Referenzen"
|
||||
main_menu: true
|
||||
weight: 70
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
Dieser Abschnitt der Kubernetes-Dokumentation enthält Referenzinformationen.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## API-Referenz
|
||||
|
||||
|
@ -58,4 +58,4 @@ Offiziell unterstützte Clientbibliotheken:
|
|||
|
||||
Ein Archiv der Designdokumente für Kubernetes-Funktionalität. Gute Ansatzpunkte sind [Kubernetes Architektur](https://git.k8s.io/community/contributors/design-proposals/architecture/architecture.md) und [Kubernetes Design Übersicht](https://git.k8s.io/community/contributors/design-proposals).
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
---
|
||||
title: kubectl Spickzettel
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
card:
|
||||
name: reference
|
||||
weight: 30
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
Siehe auch: [Kubectl Überblick](/docs/reference/kubectl/overview/) und [JsonPath Dokumentation](/docs/reference/kubectl/jsonpath).
|
||||
|
||||
Diese Seite ist eine Übersicht über den Befehl `kubectl`.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
# kubectl - Spickzettel
|
||||
|
||||
|
@ -335,9 +335,10 @@ Ausführlichkeit | Beschreibung
|
|||
`--v=8` | HTTP-Anforderungsinhalt anzeigen
|
||||
`--v=9` | HTTP-Anforderungsinhalt anzeigen, ohne den Inhalt zu kürzen.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
|
||||
* Lernen Sie mehr im [Überblick auf kubectl](/docs/reference/kubectl/overview/).
|
||||
|
||||
|
@ -347,4 +348,4 @@ Ausführlichkeit | Beschreibung
|
|||
|
||||
* Entdecken Sie mehr Community [kubectl Spickzettel](https://github.com/dennyzhang/cheatsheet-kubernetes-A4).
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
---
|
||||
title: Tools
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
Kubernetes enthält mehrere integrierte Tools, die Ihnen bei der Arbeit mit dem Kubernetes System helfen.
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
## Kubectl
|
||||
|
||||
[`kubectl`](/docs/tasks/tools/install-kubectl/) ist ein Kommandozeilenprogramm für Kubernetes. Es steuert den Kubernetes Clustermanager.
|
||||
|
@ -49,4 +49,4 @@ Verwenden Sie Kompose um:
|
|||
* Ein Docker Compose Datei in Kubernetes Objekte zu übersetzen
|
||||
* Von Ihrer lokalen Docker Entwicklung auf eine Kubernetes verwaltete Entwicklung zu wechseln
|
||||
* v1 oder v2 Docker Compose `yaml` Dateien oder [Distributed Application Bundles](https://docs.docker.com/compose/bundles/) zu konvertieren
|
||||
{{% /capture %}}
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
title: Setup
|
||||
main_menu: true
|
||||
weight: 30
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
Diese Sektion umfasst verschiedene Optionen zum Einrichten und Betrieb von Kubernetes.
|
||||
|
||||
|
@ -15,9 +15,9 @@ Sie können einen Kubernetes-Cluster auf einer lokalen Maschine, Cloud, On-Prem
|
|||
|
||||
Noch einfacher können Sie einen Kubernetes-Cluster in einer Lern- und Produktionsumgebung erstellen.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Lernumgebung
|
||||
|
||||
|
@ -99,4 +99,4 @@ Die folgende Tabelle für Produktionsumgebungs-Lösungen listet Anbieter und der
|
|||
| [VMware](https://cloud.vmware.com/) | [VMware Cloud PKS](https://cloud.vmware.com/vmware-cloud-pks) |[VMware Enterprise PKS](https://cloud.vmware.com/vmware-enterprise-pks) | [VMware Enterprise PKS](https://cloud.vmware.com/vmware-enterprise-pks) | [VMware Essential PKS](https://cloud.vmware.com/vmware-essential-pks) | |[VMware Essential PKS](https://cloud.vmware.com/vmware-essential-pks)
|
||||
| [Z.A.R.V.I.S.](https://zarvis.ai/) | ✔ | | | | | |
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
---
|
||||
title: Kubernetes lokal über Minikube betreiben
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
Minikube ist ein Tool, mit dem Kubernetes lokal einfach ausgeführt werden kann. Minikube führt einen Kubernetes-Cluster mit einem einzigen Node in einer VM auf Ihrem Laptop aus, damit Anwender Kubernetes ausprobieren oder täglich damit entwickeln können.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Minikube-Funktionen
|
||||
|
||||
|
@ -439,4 +439,4 @@ Weitere Informationen zu Minikube finden Sie im [Vorschlag](https://git.k8s.io/c
|
|||
|
||||
Beiträge, Fragen und Kommentare werden begrüßt und ermutigt! Minikube-Entwickler finden Sie in [Slack](https://kubernetes.slack.com) im #minikube Kanal (Erhalten Sie [hier](http://slack.kubernetes.io/) eine Einladung). Wir haben ausserdem die [kubernetes-dev Google Groups-Mailingliste](https://groups.google.com/forum/#!forum/kubernetes-dev). Wenn Sie in der Liste posten, fügen Sie Ihrem Betreff bitte "minikube:" voran.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
---
|
||||
title: Release erstellen
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
card:
|
||||
name: download
|
||||
weight: 20
|
||||
title: Release erstellen
|
||||
---
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
Sie können entweder eine Version aus dem Quellcode erstellen oder eine bereits kompilierte Version herunterladen.
|
||||
Wenn Sie nicht vorhaben, Kubernetes selbst zu entwickeln, empfehlen wir die Verwendung eines vorkompilierten Builds der aktuellen Version, die Sie in den [Versionshinweisen](/docs/setup/release/notes/) finden.
|
||||
|
||||
Der Kubernetes-Quellcode kann aus dem [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes) repo der heruntergeladen werden.
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Aus dem Quellcode kompilieren
|
||||
|
||||
|
@ -29,4 +29,4 @@ make release
|
|||
|
||||
Mehr Informationen zum Release-Prozess finden Sie im kubernetes/kubernetes [`build`](http://releases.k8s.io/{{< param "githubbranch" >}}/build/) Verzeichnis.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
|
|
@ -2,19 +2,19 @@
|
|||
title: Aufgaben
|
||||
main_menu: true
|
||||
weight: 50
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
---
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
Dieser Abschnitt der Kubernetes-Dokumentation enthält Seiten, die zeigen, wie man einzelne Aufgaben erledigt.
|
||||
Eine Aufgabenseite zeigt, wie man eine einzelne Aufgabe ausführt, typischerweise durch eine kurze Abfolge von Schritten.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Webbenutzeroberfläche (Dashboard)
|
||||
|
||||
|
@ -76,10 +76,11 @@ Konfigurieren und planen Sie NVIDIA-GPUs für die Verwendung durch Nodes in eine
|
|||
|
||||
Konfigurieren und verwalten Sie `HugePages` als planbare Ressource in einem Cluster.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
|
||||
Wenn Sie eine Aufgabenseite schreiben möchten, finden Sie weitere Informationen unter [Erstellen einer Pull-Anfrage für Dokumentation](/docs/home/contribute/create-pull-request/).
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
|
|
@ -5,11 +5,11 @@ feature:
|
|||
description: >
|
||||
Skaliere deine Anwendung mit einem einfachen Befehl, über die Benutzeroberfläche oder automatisch, basierend auf der CPU-Auslastung.
|
||||
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
weight: 90
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
Der Horizontal Pod Autoscaler skaliert automatisch die Anzahl der Pods eines Replication Controller, Deployment oder Replikat Set basierend auf der beobachteten CPU-Auslastung (oder, mit Unterstützung von [benutzerdefinierter Metriken](https://git.k8s.io/community/contributors/design-proposals/instrumentation/custom-metrics-api.md), von der Anwendung bereitgestellten Metriken). Beachte, dass die horizontale Pod Autoskalierung nicht für Objekte gilt, die nicht skaliert werden können, z. B. DaemonSets.
|
||||
|
||||
|
@ -17,9 +17,9 @@ Der Horizontal Pod Autoscaler ist als Kubernetes API-Ressource und einem Control
|
|||
Die Ressource bestimmt das Verhalten des Controllers.
|
||||
Der Controller passt die Anzahl der Replikate eines Replication Controller oder Deployments regelmäßig an, um die beobachtete durchschnittliche CPU-Auslastung an das vom Benutzer angegebene Ziel anzupassen.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Wie funktioniert der Horizontal Pod Autoscaler?
|
||||
|
||||
|
@ -161,12 +161,13 @@ Standardmäßig ruft der HorizontalPodAutoscaler Controller Metriken aus einer R
|
|||
|
||||
* Das Flag `--horizontal-pod-autoscaler-use-rest-clients` ist auf `true` oder ungesetzt. Wird dies auf `false` gesetzt wird die Heapster basierte Autoskalierung aktiviert, welche veraltet ist.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
|
||||
* Design Dokument [Horizontal Pod Autoscaling](https://git.k8s.io/community/contributors/design-proposals/autoscaling/horizontal-pod-autoscaler.md).
|
||||
* kubectl autoscale Befehl: [kubectl autoscale](/docs/reference/generated/kubectl/kubectl-commands/#autoscale).
|
||||
* Verwenden des [Horizontal Pod Autoscaler](/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/).
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Installieren und konfigurieren von kubectl
|
||||
content_template: templates/task
|
||||
content_type: task
|
||||
weight: 10
|
||||
card:
|
||||
name: tasks
|
||||
|
@ -8,17 +8,18 @@ card:
|
|||
title: Kubectl installieren
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
Verwenden Sie das Kubernetes Befehlszeilenprogramm, [kubectl](/docs/user-guide/kubectl/), um Anwendungen auf Kubernetes bereitzustellen und zu verwalten.
|
||||
Mit kubectl können Sie Clusterressourcen überprüfen, Komponenten erstellen, löschen und aktualisieren; Ihren neuen Cluster betrachten; und Beispielanwendungen aufrufen.
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture prerequisites %}}
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
Sie müssen eine kubectl-Version verwenden, die innerhalb eines geringfügigen Versionsunterschieds zur Version Ihres Clusters liegt. Ein v1.2-Client sollte beispielsweise mit einem v1.1, v1.2 und v1.3-Master arbeiten. Die Verwendung der neuesten Version von kubectl verhindert unvorhergesehene Probleme.
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture steps %}}
|
||||
|
||||
<!-- steps -->
|
||||
|
||||
## Kubectl installieren
|
||||
|
||||
|
@ -421,9 +422,10 @@ compinit
|
|||
{{% /tab %}}
|
||||
{{< /tabs >}}
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
[Erfahren Sie, wie Sie Ihre Anwendung starten und verfügbar machen.](/docs/tasks/access-application-cluster/service-access-application-cluster/)
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
|
|
|
@ -1,28 +1,29 @@
|
|||
---
|
||||
title: Installation von Minikube
|
||||
content_template: templates/task
|
||||
content_type: task
|
||||
weight: 20
|
||||
card:
|
||||
name: tasks
|
||||
weight: 10
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
Diese Seite zeigt Ihnen, wie Sie [Minikube](/docs/tutorials/hello-minikube) installieren, ein Programm, das einen Kubernetes-Cluster mit einem einzigen Node in einer virtuellen Maschine auf Ihrem Laptop ausführt.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture prerequisites %}}
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
|
||||
Die VT-x- oder AMD-v-Virtualisierung muss im BIOS Ihres Computers aktiviert sein. Um dies unter Linux zu überprüfen, führen Sie Folgendes aus und vergewissern Sie sich, dass die Ausgabe nicht leer ist:
|
||||
```shell
|
||||
egrep --color 'vmx|svm' /proc/cpuinfo
|
||||
```
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture steps %}}
|
||||
|
||||
<!-- steps -->
|
||||
|
||||
## Einen Hypervisor installieren
|
||||
|
||||
|
@ -106,13 +107,6 @@ Schließen Sie nach der Installation von Minikube die aktuelle CLI-Sitzung und s
|
|||
|
||||
So installieren Sie Minikube manuell unter Windows mit [Windows Installer](https://docs.microsoft.com/en-us/windows/desktop/msi/windows-installer-portal), laden Sie die Datei [`minikube-installer.exe`](https://github.com/kubernetes/minikube/releases/latest) und führen Sie den Installer aus.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
* [Kubernetes lokal über Minikube ausführen](/docs/setup/minikube/)
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
## Eine bestehende Installation bereinigen
|
||||
|
||||
|
@ -130,3 +124,8 @@ Müssen Sie die Konfigurationsdateien löschen:
|
|||
```shell
|
||||
rm -rf ~/.minikube
|
||||
```
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
|
||||
* [Kubernetes lokal über Minikube ausführen](/docs/setup/minikube/)
|
||||
|
|
|
@ -2,19 +2,19 @@
|
|||
title: Tutorials
|
||||
main_menu: true
|
||||
weight: 60
|
||||
content_template: templates/concept
|
||||
content_type: concept
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
Dieser Abschnitt der Kubernetes-Dokumentation enthält Tutorials.
|
||||
Ein Tutorial zeigt, wie Sie ein Ziel erreichen, das größer ist als eine einzelne [Aufgabe](/docs/tasks/).
|
||||
Ein Tutorial besteht normalerweise aus mehreren Abschnitten, die jeweils eine Abfolge von Schritten haben.
|
||||
Bevor Sie die einzelnen Lernprogramme durchgehen, möchten Sie möglicherweise ein Lesezeichen zur Seite mit dem [Standardisierten Glossar](/docs/reference/glossary/) setzen um später Informationen nachzuschlagen.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Grundlagen
|
||||
|
||||
|
@ -64,12 +64,13 @@ Bevor Sie die einzelnen Lernprogramme durchgehen, möchten Sie möglicherweise e
|
|||
|
||||
* [Source IP verwenden](/docs/tutorials/services/source-ip/)
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
|
||||
Wenn Sie ein Tutorial schreiben möchten, lesen Sie
|
||||
[Seitenvorlagen verwenden](/docs/home/contribute/page-templates/)
|
||||
für weitere Informationen zum Typ der Tutorial-Seite und zur Tutorial-Vorlage.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Hallo Minikube
|
||||
content_template: templates/tutorial
|
||||
content_type: tutorial
|
||||
weight: 5
|
||||
menu:
|
||||
main:
|
||||
|
@ -13,7 +13,7 @@ card:
|
|||
weight: 10
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
<!-- overview -->
|
||||
|
||||
Dieses Tutorial zeigt Ihnen, wie Sie eine einfache "Hallo Welt" Node.js-Anwendung auf Kubernetes mit [Minikube](/docs/getting-started-guides/minikube) und Katacoda ausführen.
|
||||
Katacoda bietet eine kostenlose Kubernetes-Umgebung im Browser.
|
||||
|
@ -22,17 +22,19 @@ Katacoda bietet eine kostenlose Kubernetes-Umgebung im Browser.
|
|||
Sie können dieses Tutorial auch verwenden, wenn Sie [Minikube lokal](/docs/tasks/tools/install-minikube/) installiert haben.
|
||||
{{< /note >}}
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture objectives %}}
|
||||
|
||||
## {{% heading "objectives" %}}
|
||||
|
||||
|
||||
* Stellen Sie eine Hallo-Welt-Anwendung für Minikube bereit.
|
||||
* Führen Sie die App aus.
|
||||
* Betrachten Sie die Log Dateien.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture prerequisites %}}
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
|
||||
Dieses Lernprogramm enthält ein aus den folgenden Dateien erstelltes Container-Image:
|
||||
|
||||
|
@ -42,9 +44,9 @@ Dieses Lernprogramm enthält ein aus den folgenden Dateien erstelltes Container-
|
|||
|
||||
Weitere Informationen zum `docker build` Befehl, lesen Sie die [Docker Dokumentation](https://docs.docker.com/engine/reference/commandline/build/).
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture lessoncontent %}}
|
||||
|
||||
<!-- lessoncontent -->
|
||||
|
||||
## Erstellen Sie einen Minikube-Cluster
|
||||
|
||||
|
@ -75,7 +77,7 @@ Deployments sind die empfohlene Methode zum Verwalten der Erstellung und Skalier
|
|||
Der Pod führt einen Container basierend auf dem bereitgestellten Docker-Image aus.
|
||||
|
||||
```shell
|
||||
kubectl create deployment hello-node --image=gcr.io/hello-minikube-zero-install/hello-node
|
||||
kubectl create deployment hello-node --image=k8s.gcr.io/echoserver:1.4
|
||||
```
|
||||
|
||||
2. Anzeigen des Deployments:
|
||||
|
@ -260,12 +262,13 @@ Löschen Sie optional die Minikube-VM:
|
|||
minikube delete
|
||||
```
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
|
||||
* Lernen Sie mehr über [Bereitstellungsobjekte](/docs/concepts/workloads/controllers/deployment/).
|
||||
* Lernen Sie mehr über [Anwendungen bereitstellen](/docs/user-guide/deploying-applications/).
|
||||
* Lernen Sie mehr über [Serviceobjekte](/docs/concepts/services-networking/service/).
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
|
||||
|
||||
<table style="background-color:#eeeeee">
|
||||
<tr>
|
||||
<td>
|
||||
<p><b>ACHTUNG</b></p>
|
||||
<p>Seit dem 14. März 2017 hat die Gruppe Kubernetes SIG-Docs-Maintainers mit der Migration des Benutzerhandbuch-Inhalts begonnen, wie bereits zuvor in der <a href="https://git.k8s.io/community/sig-docs">SIG Docs community</a> angekündigt. Dies wurde in der <a href="https://groups.google.com/forum/#!forum/kubernetes-sig-docs">kubernetes-sig-docs</a> Gruppe und im <a href="https://kubernetes.slack.com/messages/sig-docs/">kubernetes.slack.com #sig-docs</a> Kanal bekanntgegeben.</p>
|
||||
<p>Die Benutzerhandbücher in diesem Abschnitt werden in den Themen Tutorials, Aufgaben und Konzepte umgestaltet. Alles, was verschoben wurde, wird an seinem vorherigen Standort mit einer Benachrichtigung sowie einem Link zu seinem neuen Standort versehen. Die Reorganisation implementiert ein neues Inhaltsverzeichnis und sollte die Auffindbarkeit und Lesbarkeit der Dokumentation für ein breiteres Publikum verbessern.</p>
|
||||
<p>Bei Fragen wenden Sie sich bitte an: <a href="mailto:kubernetes-sig-docs@googlegroups.com">kubernetes-sig-docs@googlegroups.com</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
|
@ -3,9 +3,6 @@ title: "Production-Grade Container Orchestration"
|
|||
abstract: "Automated container deployment, scaling, and management"
|
||||
cid: home
|
||||
---
|
||||
{{< announcement >}}
|
||||
|
||||
{{< deprecationwarning >}}
|
||||
|
||||
{{< blocks/section id="oceanNodes" >}}
|
||||
{{% blocks/feature image="flower" %}}
|
||||
|
@ -45,7 +42,7 @@ Kubernetes is open source giving you the freedom to take advantage of on-premise
|
|||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<a href="https://events.linuxfoundation.org/kubecon-cloudnativecon-europe/?utm_source=kubernetes.io&utm_medium=nav&utm_campaign=kccnceu20" button id="desktopKCButton">Attend KubeCon in Amsterdam on August 13-16, 2020</a>
|
||||
<a href="https://events.linuxfoundation.org/kubecon-cloudnativecon-europe/?utm_source=kubernetes.io&utm_medium=nav&utm_campaign=kccnceu20" button id="desktopKCButton">Attend KubeCon EU virtually on August 17-20, 2020</a>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
|
@ -60,4 +57,4 @@ Kubernetes is open source giving you the freedom to take advantage of on-premise
|
|||
|
||||
{{< blocks/kubernetes-features >}}
|
||||
|
||||
{{< blocks/case-studies >}}
|
||||
{{< blocks/case-studies >}}
|
|
@ -8,3 +8,9 @@ menu:
|
|||
post: >
|
||||
<p>Read the latest news for Kubernetes and the containers space in general, and get technical how-tos hot off the presses.</p>
|
||||
---
|
||||
{{< comment >}}
|
||||
|
||||
For information about contributing to the blog, see
|
||||
https://kubernetes.io/docs/contribute/new-content/blogs-case-studies/#write-a-blog-post
|
||||
|
||||
{{< /comment >}}
|
||||
|
|
|
@ -4,70 +4,49 @@ date: 2017-01-30
|
|||
slug: running-mongodb-on-kubernetes-with-statefulsets
|
||||
url: /blog/2017/01/Running-Mongodb-On-Kubernetes-With-Statefulsets
|
||||
---
|
||||
_Editor's note: Today’s post is by Sandeep Dinesh, Developer Advocate, Google Cloud Platform, showing how to run a database in a container._
|
||||
_Editor's note: Today’s post is by Sandeep Dinesh, Developer Advocate, Google Cloud Platform, showing how to run a database in a container._
|
||||
|
||||
{{% warning %}}
|
||||
This post is several years old. The code examples need changes to work on a current Kubernetes cluster.
|
||||
{{% /warning %}}
|
||||
|
||||
Conventional wisdom says you can’t run a database in a container. “Containers are stateless!” they say, and “databases are pointless without state!”
|
||||
Conventional wisdom says you can’t run a database in a container. “Containers are stateless!” they say, and “databases are pointless without state!”
|
||||
|
||||
Of course, this is not true at all. At Google, everything runs in a container, including databases. You just need the right tools. [Kubernetes 1.5](https://kubernetes.io/blog/2016/12/kubernetes-1-5-supporting-production-workloads/) includes the new [StatefulSet](/docs/concepts/abstractions/controllers/statefulsets/) API object (in previous versions, StatefulSet was known as PetSet). With StatefulSets, Kubernetes makes it much easier to run stateful workloads such as databases.
|
||||
|
||||
If you’ve followed my previous posts, you know how to create a [MEAN Stack app with Docker](http://blog.sandeepdinesh.com/2015/07/running-mean-web-application-in-docker.html), then [migrate it to Kubernetes](https://medium.com/google-cloud/running-a-mean-stack-on-google-cloud-platform-with-kubernetes-149ca81c2b5d) to provide easier management and reliability, and [create a MongoDB replica set](https://medium.com/google-cloud/mongodb-replica-sets-with-kubernetes-d96606bd9474) to provide redundancy and high availability.
|
||||
If you’ve followed my previous posts, you know how to create a [MEAN Stack app with Docker](http://blog.sandeepdinesh.com/2015/07/running-mean-web-application-in-docker.html), then [migrate it to Kubernetes](https://medium.com/google-cloud/running-a-mean-stack-on-google-cloud-platform-with-kubernetes-149ca81c2b5d) to provide easier management and reliability, and [create a MongoDB replica set](https://medium.com/google-cloud/mongodb-replica-sets-with-kubernetes-d96606bd9474) to provide redundancy and high availability.
|
||||
|
||||
While the replica set in my previous blog post worked, there were some annoying steps that you needed to follow. You had to manually create a disk, a ReplicationController, and a service for each replica. Scaling the set up and down meant managing all of these resources manually, which is an opportunity for error, and would put your stateful application at risk In the previous example, we created a Makefile to ease the management of these resources, but it would have been great if Kubernetes could just take care of all of this for us.
|
||||
|
||||
With StatefulSets, these headaches finally go away. You can create and manage your MongoDB replica set natively in Kubernetes, without the need for scripts and Makefiles. Let’s take a look how.
|
||||
|
||||
_Note: StatefulSets are currently a beta resource. The [sidecar container](https://github.com/cvallance/mongo-k8s-sidecar) used for auto-configuration is also unsupported._
|
||||
While the replica set in my previous blog post worked, there were some annoying steps that you needed to follow. You had to manually create a disk, a ReplicationController, and a service for each replica. Scaling the set up and down meant managing all of these resources manually, which is an opportunity for error, and would put your stateful application at risk In the previous example, we created a Makefile to ease the management of these resources, but it would have been great if Kubernetes could just take care of all of this for us.
|
||||
|
||||
With StatefulSets, these headaches finally go away. You can create and manage your MongoDB replica set natively in Kubernetes, without the need for scripts and Makefiles. Let’s take a look how.
|
||||
|
||||
_Note: StatefulSets are currently a beta resource. The [sidecar container](https://github.com/cvallance/mongo-k8s-sidecar) used for auto-configuration is also unsupported._
|
||||
|
||||
**Prerequisites and Setup**
|
||||
|
||||
|
||||
|
||||
Before we get started, you’ll need a Kubernetes 1.5+ and the [Kubernetes command line tool](/docs/user-guide/prereqs/). If you want to follow along with this tutorial and use Google Cloud Platform, you also need the [Google Cloud SDK](http://cloud.google.com/sdk).
|
||||
|
||||
|
||||
|
||||
Once you have a [Google Cloud project created](https://console.cloud.google.com/projectcreate) and have your Google Cloud SDK setup (hint: gcloud init), we can create our cluster.
|
||||
|
||||
|
||||
|
||||
To create a Kubernetes 1.5 cluster, run the following command:
|
||||
|
||||
To create a Kubernetes 1.5 cluster, run the following command:
|
||||
|
||||
```
|
||||
gcloud container clusters create "test-cluster"
|
||||
```
|
||||
|
||||
|
||||
|
||||
This will make a three node Kubernetes cluster. Feel free to [customize the command](https://cloud.google.com/sdk/gcloud/reference/container/clusters/create) as you see fit.
|
||||
This will make a three node Kubernetes cluster. Feel free to [customize the command](https://cloud.google.com/sdk/gcloud/reference/container/clusters/create) as you see fit.
|
||||
|
||||
Then, authenticate into the cluster:
|
||||
|
||||
|
||||
|
||||
```
|
||||
gcloud container clusters get-credentials test-cluster
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
**Setting up the MongoDB replica set**
|
||||
|
||||
|
||||
|
||||
To set up the MongoDB replica set, you need three things: A [StorageClass](/docs/user-guide/persistent-volumes/#storageclasses), a [Headless Service](/docs/user-guide/services/#headless-services), and a [StatefulSet](/docs/concepts/abstractions/controllers/statefulsets/).
|
||||
|
||||
|
||||
|
||||
I’ve created the configuration files for these already, and you can clone the example from GitHub:
|
||||
|
||||
I’ve created the configuration files for these already, and you can clone the example from GitHub:
|
||||
|
||||
```
|
||||
git clone https://github.com/thesandlord/mongo-k8s-sidecar.git
|
||||
|
@ -75,10 +54,7 @@ git clone https://github.com/thesandlord/mongo-k8s-sidecar.git
|
|||
cd /mongo-k8s-sidecar/example/StatefulSet/
|
||||
```
|
||||
|
||||
|
||||
|
||||
To create the MongoDB replica set, run these two commands:
|
||||
|
||||
To create the MongoDB replica set, run these two commands:
|
||||
|
||||
```
|
||||
kubectl apply -f googlecloud\_ssd.yaml
|
||||
|
@ -86,341 +62,202 @@ kubectl apply -f googlecloud\_ssd.yaml
|
|||
kubectl apply -f mongo-statefulset.yaml
|
||||
```
|
||||
|
||||
|
||||
|
||||
That's it! With these two commands, you have launched all the components required to run an highly available and redundant MongoDB replica set.
|
||||
|
||||
|
||||
|
||||
At an high level, it looks something like this:
|
||||
|
||||
|
||||
|
||||
![](https://lh4.googleusercontent.com/ohALxLD4Ugj5FCwWqgqZ4xP9al4lTgrPDc9HsgPWYRZRz_buuYK6LKSC7A5n98DdOO-Po3Zq77Yt43-QhTWdIaXqltHI7PX0zMXAXbpiilYgdowGZapG0lJ9lgubwBj1CwNHHtXA)
|
||||
|
||||
|
||||
|
||||
Let’s examine each piece in more detail.
|
||||
|
||||
|
||||
|
||||
**StorageClass**
|
||||
|
||||
|
||||
|
||||
The storage class tells Kubernetes what kind of storage to use for the database nodes. You can set up many different types of StorageClasses in a ton of different environments. For example, if you run Kubernetes in your own datacenter, you can use [GlusterFS](https://www.gluster.org/). On GCP, your [storage choices](https://cloud.google.com/compute/docs/disks/) are SSDs and hard disks. There are currently drivers for [AWS](/docs/user-guide/persistent-volumes/#aws), [Azure](/docs/user-guide/persistent-volumes/#azure-disk), [Google Cloud](/docs/user-guide/persistent-volumes/#gce), [GlusterFS](/docs/user-guide/persistent-volumes/#glusterfs), [OpenStack Cinder](/docs/user-guide/persistent-volumes/#openstack-cinder), [vSphere](/docs/user-guide/persistent-volumes/#vsphere), [Ceph RBD](/docs/user-guide/persistent-volumes/#ceph-rbd), and [Quobyte](/docs/user-guide/persistent-volumes/#quobyte).
|
||||
|
||||
The configuration for the StorageClass looks like this:
|
||||
|
||||
|
||||
The configuration for the StorageClass looks like this:
|
||||
|
||||
|
||||
```
|
||||
kind: StorageClass
|
||||
apiVersion: storage.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: fast
|
||||
provisioner: kubernetes.io/gce-pd
|
||||
parameters:
|
||||
```yaml
|
||||
kind: StorageClass
|
||||
apiVersion: storage.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: fast
|
||||
provisioner: kubernetes.io/gce-pd
|
||||
parameters:
|
||||
type: pd-ssd
|
||||
```
|
||||
|
||||
|
||||
|
||||
This configuration creates a new StorageClass called “fast” that is backed by SSD volumes. The StatefulSet can now request a volume, and the StorageClass will automatically create it!
|
||||
|
||||
|
||||
|
||||
Deploy this StorageClass:
|
||||
|
||||
Deploy this StorageClass:
|
||||
|
||||
```
|
||||
kubectl apply -f googlecloud\_ssd.yaml
|
||||
```
|
||||
|
||||
|
||||
|
||||
**Headless Service**
|
||||
|
||||
|
||||
|
||||
Now you have created the Storage Class, you need to make a Headless Service. These are just like normal Kubernetes Services, except they don’t do any load balancing for you. When combined with StatefulSets, they can give you unique DNS addresses that let you directly access the pods! This is perfect for creating MongoDB replica sets, because our app needs to connect to all of the MongoDB nodes individually.
|
||||
|
||||
The configuration for the Headless Service looks like this:
|
||||
|
||||
|
||||
The configuration for the Headless Service looks like this:
|
||||
|
||||
|
||||
```
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
|
||||
kind: Service
|
||||
|
||||
metadata:
|
||||
|
||||
name: mongo
|
||||
|
||||
labels:
|
||||
|
||||
name: mongo
|
||||
|
||||
name: mongo
|
||||
labels:
|
||||
name: mongo
|
||||
spec:
|
||||
|
||||
ports:
|
||||
|
||||
- port: 27017
|
||||
|
||||
targetPort: 27017
|
||||
|
||||
clusterIP: None
|
||||
|
||||
selector:
|
||||
|
||||
role: mongo
|
||||
ports:
|
||||
- port: 27017
|
||||
targetPort: 27017
|
||||
clusterIP: None
|
||||
selector:
|
||||
role: mongo
|
||||
```
|
||||
|
||||
|
||||
|
||||
You can tell this is a Headless Service because the clusterIP is set to “None.” Other than that, it looks exactly the same as any normal Kubernetes Service.
|
||||
|
||||
|
||||
|
||||
**StatefulSet**
|
||||
|
||||
|
||||
|
||||
The pièce de résistance. The StatefulSet actually runs MongoDB and orchestrates everything together. StatefulSets differ from Kubernetes [ReplicaSets](/docs/user-guide/replicasets/) (not to be confused with MongoDB replica sets!) in certain ways that makes them more suited for stateful applications. Unlike Kubernetes ReplicaSets, pods created under a StatefulSet have a few unique attributes. The name of the pod is not random, instead each pod gets an ordinal name. Combined with the Headless Service, this allows pods to have stable identification. In addition, pods are created one at a time instead of all at once, which can help when bootstrapping a stateful system. You can read more about StatefulSets in the [documentation](/docs/concepts/abstractions/controllers/statefulsets/).
|
||||
|
||||
|
||||
|
||||
Just like before, [this “sidecar” container](https://github.com/cvallance/mongo-k8s-sidecar) will configure the MongoDB replica set automatically. A “sidecar” is a helper container which helps the main container do its work.
|
||||
|
||||
The configuration for the StatefulSet looks like this:
|
||||
|
||||
|
||||
The configuration for the StatefulSet looks like this:
|
||||
|
||||
|
||||
```
|
||||
```yaml
|
||||
apiVersion: apps/v1beta1
|
||||
|
||||
kind: StatefulSet
|
||||
|
||||
metadata:
|
||||
|
||||
name: mongo
|
||||
|
||||
name: mongo
|
||||
spec:
|
||||
|
||||
serviceName: "mongo"
|
||||
|
||||
replicas: 3
|
||||
|
||||
template:
|
||||
|
||||
metadata:
|
||||
|
||||
labels:
|
||||
|
||||
role: mongo
|
||||
|
||||
environment: test
|
||||
|
||||
spec:
|
||||
|
||||
terminationGracePeriodSeconds: 10
|
||||
|
||||
containers:
|
||||
|
||||
- name: mongo
|
||||
|
||||
image: mongo
|
||||
|
||||
command:
|
||||
|
||||
- mongod
|
||||
|
||||
- "--replSet"
|
||||
|
||||
- rs0
|
||||
|
||||
- "--smallfiles"
|
||||
|
||||
- "--noprealloc"
|
||||
|
||||
ports:
|
||||
|
||||
- containerPort: 27017
|
||||
|
||||
volumeMounts:
|
||||
|
||||
- name: mongo-persistent-storage
|
||||
|
||||
mountPath: /data/db
|
||||
|
||||
- name: mongo-sidecar
|
||||
|
||||
image: cvallance/mongo-k8s-sidecar
|
||||
|
||||
env:
|
||||
|
||||
- name: MONGO\_SIDECAR\_POD\_LABELS
|
||||
|
||||
value: "role=mongo,environment=test"
|
||||
|
||||
volumeClaimTemplates:
|
||||
|
||||
- metadata:
|
||||
|
||||
name: mongo-persistent-storage
|
||||
|
||||
annotations:
|
||||
|
||||
volume.beta.kubernetes.io/storage-class: "fast"
|
||||
|
||||
spec:
|
||||
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
|
||||
resources:
|
||||
|
||||
requests:
|
||||
|
||||
storage: 100Gi
|
||||
selector:
|
||||
matchLabels:
|
||||
role: mongo
|
||||
environment: test
|
||||
serviceName: "mongo"
|
||||
replicas: 3
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
role: mongo
|
||||
environment: test
|
||||
spec:
|
||||
terminationGracePeriodSeconds: 10
|
||||
containers:
|
||||
- name: mongo
|
||||
image: mongo
|
||||
command:
|
||||
- mongod
|
||||
- "--replSet"
|
||||
- rs0
|
||||
- "--smallfiles"
|
||||
- "--noprealloc"
|
||||
ports:
|
||||
- containerPort: 27017
|
||||
volumeMounts:
|
||||
- name: mongo-persistent-storage
|
||||
mountPath: /data/db
|
||||
- name: mongo-sidecar
|
||||
image: cvallance/mongo-k8s-sidecar
|
||||
env:
|
||||
- name: MONGO_SIDECAR_POD_LABELS
|
||||
value: "role=mongo,environment=test"
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: mongo-persistent-storage
|
||||
spec:
|
||||
storageClassName: "fast"
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: 100Gi
|
||||
```
|
||||
|
||||
|
||||
|
||||
It’s a little long, but fairly straightforward.
|
||||
|
||||
|
||||
|
||||
The first second describes the StatefulSet object. Then, we move into the Metadata section, where you can specify labels and the number of replicas.
|
||||
|
||||
Next comes the pod spec. The terminationGracePeriodSeconds is used to gracefully shutdown the pod when you scale down the number of replicas, which is important for databases! Then the configurations for the two containers is shown. The first one runs MongoDB with command line flags that configure the replica set name. It also mounts the persistent storage volume to /data/db, the location where MongoDB saves its data. The second container runs the sidecar.
|
||||
|
||||
|
||||
Next comes the pod spec. The terminationGracePeriodSeconds is used to gracefully shutdown the pod when you scale down the number of replicas, which is important for databases! Then the configurations for the two containers is shown. The first one runs MongoDB with command line flags that configure the replica set name. It also mounts the persistent storage volume to /data/db, the location where MongoDB saves its data. The second container runs the sidecar.
|
||||
|
||||
|
||||
|
||||
Finally, there is the volumeClaimTemplates. This is what talks to the StorageClass we created before to provision the volume. It will provision a 100 GB disk for each MongoDB replica.
|
||||
|
||||
|
||||
Finally, there is the volumeClaimTemplates. This is what talks to the StorageClass we created before to provision the volume. It will provision a 100 GB disk for each MongoDB replica.
|
||||
|
||||
**Using the MongoDB replica set**
|
||||
|
||||
|
||||
|
||||
At this point, you should have three pods created in your cluster. These correspond to the three nodes in your MongoDB replica set. You can see them with this command:
|
||||
|
||||
At this point, you should have three pods created in your cluster. These correspond to the three nodes in your MongoDB replica set. You can see them with this command:
|
||||
|
||||
```
|
||||
kubectl get pods
|
||||
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
|
||||
mongo-0 2/2 Running 0 3m
|
||||
|
||||
mongo-1 2/2 Running 0 3m
|
||||
|
||||
mongo-2 2/2 Running 0 3m
|
||||
```
|
||||
|
||||
Each pod in a StatefulSet backed by a Headless Service will have a stable DNS name. The template follows this format: \<pod-name\>.\<service-name\>
|
||||
|
||||
|
||||
Each pod in a StatefulSet backed by a Headless Service will have a stable DNS name. The template follows this format: \<pod-name\>.\<service-name\>
|
||||
|
||||
This means the DNS names for the MongoDB replica set are:
|
||||
|
||||
|
||||
This means the DNS names for the MongoDB replica set are:
|
||||
|
||||
```
|
||||
mongo-0.mongo
|
||||
|
||||
mongo-1.mongo
|
||||
|
||||
mongo-2.mongo
|
||||
```
|
||||
|
||||
You can use these names directly in the [connection string URI](http://docs.mongodb.com/manual/reference/connection-string) of your app.
|
||||
|
||||
|
||||
You can use these names directly in the [connection string URI](http://docs.mongodb.com/manual/reference/connection-string) of your app.
|
||||
|
||||
In this case, the connection string URI would be:
|
||||
|
||||
In this case, the connection string URI would be:
|
||||
|
||||
```
|
||||
“mongodb://mongo-0.mongo,mongo-1.mongo,mongo-2.mongo:27017/dbname\_?”
|
||||
mongodb://mongo-0.mongo,mongo-1.mongo,mongo-2.mongo:27017/dbname\_?
|
||||
```
|
||||
|
||||
That’s it!
|
||||
|
||||
That’s it!
|
||||
|
||||
**Scaling the MongoDB replica set**
|
||||
|
||||
A huge advantage of StatefulSets is that you can scale them just like Kubernetes ReplicaSets. If you want 5 MongoDB Nodes instead of 3, just run the scale command:
|
||||
|
||||
**Scaling the MongoDB replica set**
|
||||
|
||||
A huge advantage of StatefulSets is that you can scale them just like Kubernetes ReplicaSets. If you want 5 MongoDB Nodes instead of 3, just run the scale command:
|
||||
|
||||
```
|
||||
kubectl scale --replicas=5 statefulset mongo
|
||||
```
|
||||
|
||||
The sidecar container will automatically configure the new MongoDB nodes to join the replica set.
|
||||
|
||||
The sidecar container will automatically configure the new MongoDB nodes to join the replica set.
|
||||
Include the two new nodes (mongo-3.mongo & mongo-4.mongo) in your connection string URI and you are good to go. Too easy!
|
||||
|
||||
Include the two new nodes (mongo-3.mongo & mongo-4.mongo) in your connection string URI and you are good to go. Too easy!
|
||||
**Cleaning Up**
|
||||
|
||||
**Cleaning Up**
|
||||
|
||||
To clean up the deployed resources, delete the StatefulSet, Headless Service, and the provisioned volumes.
|
||||
|
||||
Delete the StatefulSet:
|
||||
To clean up the deployed resources, delete the StatefulSet, Headless Service, and the provisioned volumes.
|
||||
|
||||
Delete the StatefulSet:
|
||||
|
||||
```
|
||||
kubectl delete statefulset mongo
|
||||
```
|
||||
|
||||
|
||||
|
||||
Delete the Service:
|
||||
|
||||
Delete the Service:
|
||||
|
||||
```
|
||||
kubectl delete svc mongo
|
||||
```
|
||||
|
||||
|
||||
|
||||
Delete the Volumes:
|
||||
|
||||
|
||||
|
||||
Delete the Volumes:
|
||||
|
||||
```
|
||||
kubectl delete pvc -l role=mongo
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
Finally, you can delete the test cluster:
|
||||
|
||||
|
||||
|
||||
Finally, you can delete the test cluster:
|
||||
|
||||
```
|
||||
gcloud container clusters delete "test-cluster"
|
||||
```
|
||||
|
||||
|
||||
|
||||
Happy Hacking!
|
||||
|
||||
|
||||
|
||||
For more cool Kubernetes and Container blog posts, follow me on [Twitter](https://twitter.com/sandeepdinesh) and [Medium](https://medium.com/@SandeepDinesh).
|
||||
|
||||
|
||||
|
||||
_--Sandeep Dinesh, Developer Advocate, Google Cloud Platform._
|
||||
|
|
|
@ -76,7 +76,7 @@ Each Special Interest Group (SIG) within the community continues to deliver
|
|||
the most-requested enhancements, fixes, and functionality for their respective
|
||||
specialty areas. For a complete list of inclusions by SIG, please visit the
|
||||
[release
|
||||
notes](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.10.md#110-release-notes).
|
||||
notes](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.10.md#110-release-notes).
|
||||
|
||||
## Availability
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ The local persistent volume beta feature is not complete by far. Some notable en
|
|||
|
||||
[Pod disruption budget](/docs/concepts/workloads/pods/disruptions/) is also very important for those workloads that must maintain quorum. Setting a disruption budget for your workload ensures that it does not drop below quorum due to voluntary disruption events, such as node drains during upgrade.
|
||||
|
||||
[Pod affinity and anti-affinity](/docs/concepts/configuration/assign-pod-node/#inter-pod-affinity-and-anti-affinity-beta-feature) ensures that your workloads stay either co-located or spread out across failure domains. If you have multiple local persistent volumes available on a single node, it may be preferable to specify an pod anti-affinity policy to spread your workload across nodes. Note that if you want multiple pods to share the same local persistent volume, you do not need to specify a pod affinity policy. The scheduler understands the locality constraints of the local persistent volume and schedules your pod to the correct node.
|
||||
[Pod affinity and anti-affinity](/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity-beta-feature) ensures that your workloads stay either co-located or spread out across failure domains. If you have multiple local persistent volumes available on a single node, it may be preferable to specify an pod anti-affinity policy to spread your workload across nodes. Note that if you want multiple pods to share the same local persistent volume, you do not need to specify a pod affinity policy. The scheduler understands the locality constraints of the local persistent volume and schedules your pod to the correct node.
|
||||
|
||||
## Getting involved
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ Why is RuntimeClass a pod level concept? The Kubernetes resource model expects c
|
|||
|
||||
## What's next?
|
||||
|
||||
The RuntimeClass resource is an important foundation for surfacing runtime properties to the control plane. For example, to implement scheduler support for clusters with heterogeneous nodes supporting different runtimes, we might add [NodeAffinity](/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity) terms to the RuntimeClass definition. Another area to address is managing the variable resource requirements to run pods of different runtimes. The [Pod Overhead proposal](https://docs.google.com/document/d/1EJKT4gyl58-kzt2bnwkv08MIUZ6lkDpXcxkHqCvvAp4/preview) was an early take on this that aligns nicely with the RuntimeClass design, and may be pursued further.
|
||||
The RuntimeClass resource is an important foundation for surfacing runtime properties to the control plane. For example, to implement scheduler support for clusters with heterogeneous nodes supporting different runtimes, we might add [NodeAffinity](/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) terms to the RuntimeClass definition. Another area to address is managing the variable resource requirements to run pods of different runtimes. The [Pod Overhead proposal](https://docs.google.com/document/d/1EJKT4gyl58-kzt2bnwkv08MIUZ6lkDpXcxkHqCvvAp4/preview) was an early take on this that aligns nicely with the RuntimeClass design, and may be pursued further.
|
||||
|
||||
Many other RuntimeClass extensions have also been proposed, and will be revisited as the feature continues to develop and mature. A few more extensions that are being considered include:
|
||||
|
||||
|
|
|
@ -60,9 +60,7 @@ using `kube-apiserver --feature-gates DryRun=true`.
|
|||
If you have dynamic admission controllers, you might have to fix them to:
|
||||
|
||||
- Remove any side-effects when the dry-run parameter is specified on the webhook request,
|
||||
- Specify in the [`sideEffects`](/docs/reference/generated/kubernetes-api/v1.13/#webhook-v1beta1-admissionregistration)
|
||||
field of the `admissionregistration.k8s.io/v1beta1.Webhook` object to indicate that the object doesn't
|
||||
have side-effects on dry-run (or at all).
|
||||
- Specify in the [`sideEffects`](https://v1-13.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.13/#webhook-v1beta1-admissionregistration) field of the `admissionregistration.k8s.io/v1beta1.Webhook` object to indicate that the object doesn't have side-effects on dry-run (or at all).
|
||||
|
||||
### How to use it
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ In this way, admission controllers and policy management help make sure that app
|
|||
|
||||
To illustrate how admission controller webhooks can be leveraged to establish custom security policies, let’s consider an example that addresses one of the shortcomings of Kubernetes: a lot of its defaults are optimized for ease of use and reducing friction, sometimes at the expense of security. One of these settings is that containers are by default allowed to run as root (and, without further configuration and no `USER` directive in the Dockerfile, will also do so). Even though containers are isolated from the underlying host to a certain extent, running containers as root does increase the risk profile of your deployment— and should be avoided as one of many [security best practices](https://www.stackrox.com/post/2018/12/6-container-security-best-practices-you-should-be-following/). The [recently exposed runC vulnerability](https://www.stackrox.com/post/2019/02/the-runc-vulnerability-a-deep-dive-on-protecting-yourself/) ([CVE-2019-5736](https://nvd.nist.gov/vuln/detail/CVE-2019-5736)), for example, could be exploited only if the container ran as root.
|
||||
|
||||
You can use a custom mutating admission controller webhook to apply more secure defaults: unless explicitly requested, our webhook will ensure that pods run as a non-root user (we assign the user ID 1234 if no explicit assignment has been made). Note that this setup does not prevent you from deploying any workloads in your cluster, including those that legitimately require running as root. It only requires you to explicitly enable this risker mode of operation in the deployment configuration, while defaulting to non-root mode for all other workloads.
|
||||
You can use a custom mutating admission controller webhook to apply more secure defaults: unless explicitly requested, our webhook will ensure that pods run as a non-root user (we assign the user ID 1234 if no explicit assignment has been made). Note that this setup does not prevent you from deploying any workloads in your cluster, including those that legitimately require running as root. It only requires you to explicitly enable this riskier mode of operation in the deployment configuration, while defaulting to non-root mode for all other workloads.
|
||||
|
||||
The full code along with deployment instructions can be found in our accompanying [GitHub repository](https://github.com/stackrox/admission-controller-webhook-demo). Here, we will highlight a few of the more subtle aspects about how webhooks work.
|
||||
|
||||
|
@ -80,7 +80,7 @@ webhooks:
|
|||
resources: ["pods"]
|
||||
```
|
||||
|
||||
This configuration defines a `webhook webhook-server.webhook-demo.svc`, and instructs the Kubernetes API server to consult the service `webhook-server` in n`amespace webhook-demo` whenever a pod is created by making a HTTP POST request to the `/mutate` URL. For this configuration to work, several prerequisites have to be met.
|
||||
This configuration defines a `webhook webhook-server.webhook-demo.svc`, and instructs the Kubernetes API server to consult the service `webhook-server` in `namespace webhook-demo` whenever a pod is created by making a HTTP POST request to the `/mutate` URL. For this configuration to work, several prerequisites have to be met.
|
||||
|
||||
## Webhook REST API
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ Introducing CSI plugin support for out-of-tree providers, enabling Windows nodes
|
|||
|
||||
## Introducing Endpoint Slices
|
||||
|
||||
The release of Kubernetes 1.16 includes an exciting new alpha feature: the EndpointSlice API. This API provides a scalable and extensible alternative to the [Endpoints](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#endpoints-v1-core) resource, which dates back to the very first versions of Kubernetes. Behind the scenes, Endpoints play a big role in network routing within Kubernetes. Each Service endpoint is tracked within these resources - kube-proxy uses them for generating proxy rules that allow pods to communicate with each other so easily in Kubernetes, and many ingress controllers use them to route HTTP traffic directly to pods.
|
||||
The release of Kubernetes 1.16 includes an exciting new alpha feature: the EndpointSlice API. This API provides a scalable and extensible alternative to the [Endpoints](https://v1-16.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#endpoints-v1-core) resource, which dates back to the very first versions of Kubernetes. Behind the scenes, Endpoints play a big role in network routing within Kubernetes. Each Service endpoint is tracked within these resources - kube-proxy uses them for generating proxy rules that allow pods to communicate with each other so easily in Kubernetes, and many ingress controllers use them to route HTTP traffic directly to pods.
|
||||
|
||||
### Providing Greater Scalability
|
||||
|
||||
|
|
|
@ -97,7 +97,16 @@ reviews-v2-ccffdd984-9jnsj 2/2 Running 0 101s
|
|||
reviews-v3-98dc67b68-nzw97 2/2 Running 0 101s
|
||||
```
|
||||
|
||||
This command outputs useful data, so let’s take a second to understand it. If you examine the READY column, each pod has two containers running: the service and an Envoy sidecar injected alongside it. Another thing to highlight is that there are three review pods but only 1 review service. The Envoy sidecar will load balance the traffic to three different review pods that contain different versions, giving us the ability to A/B test our changes. With that said, you should now be able to access your product page!
|
||||
This command outputs useful data, so let’s take a second to understand it. If you examine the READY column, each pod has two containers running: the service and an Envoy sidecar injected alongside it. Another thing to highlight is that there are three review pods but only 1 review service. The Envoy sidecar will load balance the traffic to three different review pods that contain different versions, giving us the ability to A/B test our changes. We have one step before we can access the deployed application. We need to add an additional annotation to the `productpage` service. To do so, run:
|
||||
|
||||
```
|
||||
$ kubectl annotate service productpage ingress.kubernetes.io/service-upstream=true
|
||||
service/productpage annotated
|
||||
```
|
||||
|
||||
Both the API gateway (Kong) and the service mesh (Istio) can handle the load-balancing. Without the additional `ingress.kubernetes.io/service-upstream: "true"` annotation, Kong will try to load-balance by selecting its own endpoint/target from the productpage service. This causes Envoy to receive that pod’s IP as the upstream local address, instead of the service’s cluster IP. But we want the service's cluster IP so that Envoy can properly load balance.
|
||||
|
||||
With that added, you should now be able to access your product page!
|
||||
|
||||
```
|
||||
$ kubectl exec -it $(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}') -c ratings -- curl productpage:9080/productpage | grep -o "<title>.*</title>"
|
||||
|
@ -150,6 +159,8 @@ metadata:
|
|||
name: do-not-preserve-host
|
||||
route:
|
||||
preserve_host: false
|
||||
upstream:
|
||||
host_header: productpage.default.svc
|
||||
" | kubectl apply -f -
|
||||
kongingress.configuration.konghq.com/do-not-preserve-host created
|
||||
```
|
|
@ -37,8 +37,7 @@ SIG-CLI was debating the need for a debug utility for quite some time already. W
|
|||
|
||||
### Introducing Windows CSI support alpha for Kubernetes
|
||||
|
||||
With the release of Kubernetes 1.18, an alpha version of CSI Proxy for Windows is getting released. CSI proxy enables non-privileged (pre-approved) containers to perform privileged storage operations on Windows. CSI drivers can now be supported in Windows by leveraging CSI proxy.
|
||||
|
||||
The alpha version of CSI Proxy for Windows is being released with Kubernetes 1.18. CSI proxy enables CSI Drivers on Windows by allowing containers in Windows to perform privileged storage operations.
|
||||
|
||||
## Other Updates
|
||||
|
||||
|
|
|
@ -0,0 +1,503 @@
|
|||
---
|
||||
layout: blog
|
||||
title: "Kubernetes Topology Manager Moves to Beta - Align Up!"
|
||||
date: 2020-04-01
|
||||
slug: kubernetes-1-18-feature-topoloy-manager-beta
|
||||
---
|
||||
|
||||
**Authors:** Kevin Klues (NVIDIA), Victor Pickard (Red Hat), Conor Nolan (Intel)
|
||||
|
||||
This blog post describes the **<code>TopologyManager</code>**, a beta feature of Kubernetes in release 1.18. The **<code>TopologyManager</code>** feature enables NUMA alignment of CPUs and peripheral devices (such as SR-IOV VFs and GPUs), allowing your workload to run in an environment optimized for low-latency.
|
||||
|
||||
Prior to the introduction of the **<code>TopologyManager</code>**, the CPU and Device Manager would make resource allocation decisions independent of each other. This could result in undesirable allocations on multi-socket systems, causing degraded performance on latency critical applications. With the introduction of the **<code>TopologyManager</code>**, we now have a way to avoid this.
|
||||
|
||||
This blog post covers:
|
||||
|
||||
1. A brief introduction to NUMA and why it is important
|
||||
1. The policies available to end-users to ensure NUMA alignment of CPUs and devices
|
||||
1. The internal details of how the **<code>TopologyManager</code>** works
|
||||
1. Current limitations of the **<code>TopologyManager</code>**
|
||||
1. Future directions of the **<code>TopologyManager</code>**
|
||||
|
||||
## So, what is NUMA and why do I care?
|
||||
|
||||
The term NUMA stands for Non-Uniform Memory Access. It is a technology available on multi-cpu systems that allows different CPUs to access different parts of memory at different speeds. Any memory directly connected to a CPU is considered "local" to that CPU and can be accessed very fast. Any memory not directly connected to a CPU is considered "non-local" and will have variable access times depending on how many interconnects must be passed through in order to reach it. On modern systems, the idea of having "local" vs. "non-local" memory can also be extended to peripheral devices such as NICs or GPUs. For high performance, CPUs and devices should be allocated such that they have access to the same local memory.
|
||||
|
||||
All memory on a NUMA system is divided into a set of "NUMA nodes", with each node representing the local memory for a set of CPUs or devices. We talk about an individual CPU as being part of a NUMA node if its local memory is associated with that NUMA node.
|
||||
|
||||
We talk about a peripheral device as being part of a NUMA node based on the shortest number of interconnects that must be passed through in order to reach it.
|
||||
|
||||
For example, in Figure 1, CPUs 0-3 are said to be part of NUMA node 0, whereas CPUs 4-7 are part of NUMA node 1. Likewise GPU 0 and NIC 0 are said to be part of NUMA node 0 because they are attached to Socket 0, whose CPUs are all part of NUMA node 0. The same is true for GPU 1 and NIC 1 on NUMA node 1.
|
||||
|
||||
<p align="center">
|
||||
<img height="300" src="/images/blog/2020-03-25-kubernetes-1.18-release-announcement/example-numa-system.png">
|
||||
</p>
|
||||
|
||||
|
||||
**Figure 1:** An example system with 2 NUMA nodes, 2 Sockets with 4 CPUs each, 2 GPUs, and 2 NICs. CPUs on Socket 0, GPU 0, and NIC 0 are all part of NUMA node 0. CPUs on Socket 1, GPU 1, and NIC 1 are all part of NUMA node 1.
|
||||
|
||||
|
||||
Although the example above shows a 1-1 mapping of NUMA Node to Socket, this is not necessarily true in the general case. There may be multiple sockets on a single NUMA node, or individual CPUs of a single socket may be connected to different NUMA nodes. Moreover, emerging technologies such as Sub-NUMA Clustering ([available on recent intel CPUs](https://software.intel.com/en-us/articles/intel-xeon-processor-scalable-family-technical-overview)) allow single CPUs to be associated with multiple NUMA nodes so long as their memory access times to both nodes are the same (or have a negligible difference).
|
||||
|
||||
The **<code>TopologyManager</code>** has been built to handle all of these scenarios.
|
||||
|
||||
## Align Up! It's a TeaM Effort!
|
||||
|
||||
As previously stated, the **<code>TopologyManager</code>** allows users to align their CPU and peripheral device allocations by NUMA node. There are several policies available for this:
|
||||
|
||||
* **<code>none:</code>** this policy will not attempt to do any alignment of resources. It will act the same as if the **<code>TopologyManager</code>** were not present at all. This is the default policy.
|
||||
* **<code>best-effort:</code>** with this policy, the **<code>TopologyManager</code>** will attempt to align allocations on NUMA nodes as best it can, but will always allow the pod to start even if some of the allocated resources are not aligned on the same NUMA node.
|
||||
* **<code>restricted:</code>** this policy is the same as the **<code>best-effort</code>** policy, except it will fail pod admission if allocated resources cannot be aligned properly. Unlike with the **<code>single-numa-node</code>** policy, some allocations may come from multiple NUMA nodes if it is impossible to _ever_ satisfy the allocation request on a single NUMA node (e.g. 2 devices are requested and the only 2 devices on the system are on different NUMA nodes).
|
||||
* **<code>single-numa-node:</code>** this policy is the most restrictive and will only allow a pod to be admitted if _all_ requested CPUs and devices can be allocated from exactly one NUMA node.
|
||||
|
||||
It is important to note that the selected policy is applied to each container in a pod spec individually, rather than aligning resources across all containers together.
|
||||
|
||||
Moreover, a single policy is applied to _all_ pods on a node via a global **<code>kubelet</code>** flag, rather than allowing users to select different policies on a pod-by-pod basis (or a container-by-container basis). We hope to relax this restriction in the future.
|
||||
|
||||
The **<code>kubelet</code>** flag to set one of these policies can be seen below:
|
||||
|
||||
|
||||
```
|
||||
--topology-manager-policy=
|
||||
[none | best-effort | restricted | single-numa-node]
|
||||
```
|
||||
|
||||
|
||||
Additionally, the **<code>TopologyManager</code>** is protected by a feature gate. This feature gate has been available since Kubernetes 1.16, but has only been enabled by default since 1.18.
|
||||
|
||||
The feature gate can be enabled or disabled as follows (as described in more detail [here](https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/)):
|
||||
|
||||
|
||||
```
|
||||
--feature-gates="...,TopologyManager=<true|false>"
|
||||
```
|
||||
|
||||
|
||||
In order to trigger alignment according to the selected policy, a user must request CPUs and peripheral devices in their pod spec, according to a certain set of requirements.
|
||||
|
||||
For peripheral devices, this means requesting devices from the available resources provided by a device plugin (e.g. **<code>intel.com/sriov</code>**, **<code>nvidia.com/gpu</code>**, etc.). This will only work if the device plugin has been extended to integrate properly with the **<code>TopologyManager</code>**. Currently, the only plugins known to have this extension are the [Nvidia GPU device plugin](https://github.com/NVIDIA/k8s-device-plugin/blob/5cb45d52afdf5798a40f8d0de049bce77f689865/nvidia.go#L74), and the [Intel SRIOV network device plugin](https://github.com/intel/sriov-network-device-plugin/blob/30e33f1ce2fc7b45721b6de8c8207e65dbf2d508/pkg/resources/pciNetDevice.go#L80). Details on how to extend a device plugin to integrate with the **<code>TopologyManager</code>** can be found [here](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/#device-plugin-integration-with-the-topology-manager).
|
||||
|
||||
For CPUs, this requires that the **<code>CPUManager</code>** has been configured with its **<code>--static</code>** policy enabled and that the pod is running in the Guaranteed QoS class (i.e. all CPU and memory **<code>limits</code>** are equal to their respective CPU and memory **<code>requests</code>**). CPUs must also be requested in whole number values (e.g. **<code>1</code>**, **<code>2</code>**, **<code>1000m</code>**, etc). Details on how to set the **<code>CPUManager</code>** policy can be found [here](https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/#cpu-management-policies).
|
||||
|
||||
For example, assuming the **<code>CPUManager</code>** is running with its **<code>--static</code>** policy enabled and the device plugins for **<code>gpu-vendor.com</code>**, and **<code>nic-vendor.com</code>** have been extended to integrate with the **<code>TopologyManager</code>** properly, the pod spec below is sufficient to trigger the **<code>TopologyManager</code>** to run its selected policy:
|
||||
|
||||
```
|
||||
spec:
|
||||
containers:
|
||||
- name: numa-aligned-container
|
||||
image: alpine
|
||||
resources:
|
||||
limits:
|
||||
cpu: 2
|
||||
memory: 200Mi
|
||||
gpu-vendor.com/gpu: 1
|
||||
nic-vendor.com/nic: 1
|
||||
```
|
||||
|
||||
Following Figure 1 from the previous section, this would result in one of the following aligned allocations:
|
||||
|
||||
```
|
||||
{cpu: {0, 1}, gpu: 0, nic: 0}
|
||||
{cpu: {0, 2}, gpu: 0, nic: 0}
|
||||
{cpu: {0, 3}, gpu: 0, nic: 0}
|
||||
{cpu: {1, 2}, gpu: 0, nic: 0}
|
||||
{cpu: {1, 3}, gpu: 0, nic: 0}
|
||||
{cpu: {2, 3}, gpu: 0, nic: 0}
|
||||
|
||||
{cpu: {4, 5}, gpu: 1, nic: 1}
|
||||
{cpu: {4, 6}, gpu: 1, nic: 1}
|
||||
{cpu: {4, 7}, gpu: 1, nic: 1}
|
||||
{cpu: {5, 6}, gpu: 1, nic: 1}
|
||||
{cpu: {5, 7}, gpu: 1, nic: 1}
|
||||
{cpu: {6, 7}, gpu: 1, nic: 1}
|
||||
```
|
||||
|
||||
And that’s it! Just follow this pattern to have the **<code>TopologyManager</code>** ensure NUMA alignment across containers that request topology-aware devices and exclusive CPUs.
|
||||
|
||||
**NOTE:** if a pod is rejected by one of the **<code>TopologyManager</code>** policies, it will be placed in a **<code>Terminated</code>** state with a pod admission error and a reason of "**<code>TopologyAffinityError</code>**". Once a pod is in this state, the Kubernetes scheduler will not attempt to reschedule it. It is therefore recommended to use a [**<code>Deployment</code>**](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#creating-a-deployment) with replicas to trigger a redeploy of the pod on such a failure. An [external control loop](https://kubernetes.io/docs/concepts/architecture/controller/) can also be implemented to trigger a redeployment of pods that have a **<code>TopologyAffinityError</code>**.
|
||||
|
||||
## This is great, so how does it work under the hood?
|
||||
|
||||
Pseudocode for the primary logic carried out by the **<code>TopologyManager</code>** can be seen below:
|
||||
|
||||
```
|
||||
for container := range append(InitContainers, Containers...) {
|
||||
for provider := range HintProviders {
|
||||
hints += provider.GetTopologyHints(container)
|
||||
}
|
||||
|
||||
bestHint := policy.Merge(hints)
|
||||
|
||||
for provider := range HintProviders {
|
||||
provider.Allocate(container, bestHint)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The following diagram summarizes the steps taken during this loop:
|
||||
|
||||
<p align="center">
|
||||
<img weight="200" height="200" src="/images/blog/2020-03-25-kubernetes-1.18-release-announcement/numa-steps-during-loop.png">
|
||||
</p>
|
||||
|
||||
The steps themselves are:
|
||||
|
||||
1. Loop over all containers in a pod.
|
||||
1. For each container, gather "**<code>TopologyHints</code>**" from a set of "**<code>HintProviders</code>**" for each topology-aware resource type requested by the container (e.g. **<code>gpu-vendor.com/gpu</code>**, **<code>nic-vendor.com/nic</code>**, **<code>cpu</code>**, etc.).
|
||||
1. Using the selected policy, merge the gathered **<code>TopologyHints</code>** to find the "best" hint that aligns resource allocations across all resource types.
|
||||
1. Loop back over the set of hint providers, instructing them to allocate the resources they control using the merged hint as a guide.
|
||||
1. This loop runs at pod admission time and will fail to admit the pod if any of these steps fail or alignment cannot be satisfied according to the selected policy. Any resources allocated before the failure are cleaned up accordingly.
|
||||
|
||||
The following sections go into more detail on the exact structure of **<code>TopologyHints</code>** and **<code>HintProviders</code>**, as well as some details on the merge strategies used by each policy.
|
||||
|
||||
### TopologyHints
|
||||
|
||||
A **<code>TopologyHint</code>** encodes a set of constraints from which a given resource request can be satisfied. At present, the only constraint we consider is NUMA alignment. It is defined as follows:
|
||||
|
||||
```
|
||||
type TopologyHint struct {
|
||||
NUMANodeAffinity bitmask.BitMask
|
||||
Preferred bool
|
||||
}
|
||||
```
|
||||
|
||||
The **<code>NUMANodeAffinity</code>** field contains a bitmask of NUMA nodes where a resource request can be satisfied. For example, the possible masks on a system with 2 NUMA nodes include:
|
||||
|
||||
```
|
||||
{00}, {01}, {10}, {11}
|
||||
```
|
||||
|
||||
The **<code>Preferred</code>** field contains a boolean that encodes whether the given hint is "preferred" or not. With the **<code>best-effort</code>** policy, preferred hints will be given preference over non-preferred hints when generating a "best" hint. With the **<code>restricted</code>** and **<code>single-numa-node</code>** policies, non-preferred hints will be rejected.
|
||||
|
||||
In general, **<code>HintProviders</code>** generate **<code>TopologyHints</code>** by looking at the set of currently available resources that can satisfy a resource request. More specifically, they generate one **<code>TopologyHint</code>** for every possible mask of NUMA nodes where that resource request can be satisfied. If a mask cannot satisfy the request, it is omitted. For example, a **<code>HintProvider</code>** might provide the following hints on a system with 2 NUMA nodes when being asked to allocate 2 resources. These hints encode that both resources could either come from a single NUMA node (either 0 or 1), or they could each come from different NUMA nodes (but we prefer for them to come from just one).
|
||||
|
||||
```
|
||||
{01: True}, {10: True}, {11: False}
|
||||
```
|
||||
|
||||
At present, all **<code>HintProviders</code>** set the **<code>Preferred</code>** field to **<code>True</code>** if and only if the **<code>NUMANodeAffinity</code>** encodes a _minimal_ set of NUMA nodes that can satisfy the resource request. Normally, this will only be **<code>True</code>** for **<code>TopologyHints</code>** with a single NUMA node set in their bitmask. However, it may also be **<code>True</code>** if the only way to _ever_ satisfy the resource request is to span multiple NUMA nodes (e.g. 2 devices are requested and the only 2 devices on the system are on different NUMA nodes):
|
||||
|
||||
```
|
||||
{0011: True}, {0111: False}, {1011: False}, {1111: False}
|
||||
```
|
||||
|
||||
**NOTE:** Setting of the **<code>Preferred</code>** field in this way is _not_ based on the set of currently available resources. It is based on the ability to physically allocate the number of requested resources on some minimal set of NUMA nodes.
|
||||
|
||||
In this way, it is possible for a **<code>HintProvider</code>** to return a list of hints with _all_ **<code>Preferred</code>** fields set to **<code>False</code>** if an actual preferred allocation cannot be satisfied until other containers release their resources. For example, consider the following scenario from the system in Figure 1:
|
||||
|
||||
1. All but 2 CPUs are currently allocated to containers
|
||||
1. The 2 remaining CPUs are on different NUMA nodes
|
||||
1. A new container comes along asking for 2 CPUs
|
||||
|
||||
In this case, the only generated hint would be **<code>{11: False}</code>** and not **<code>{11: True}</code>**. This happens because it _is_ possible to allocate 2 CPUs from the same NUMA node on this system (just not right now, given the current allocation state). The idea being that it is better to fail pod admission and retry the deployment when the minimal alignment can be satisfied than to allow a pod to be scheduled with sub-optimal alignment.
|
||||
|
||||
### HintProviders
|
||||
|
||||
A **<code>HintProvider</code>** is a component internal to the **<code>kubelet</code>** that coordinates aligned resource allocations with the **<code>TopologyManager</code>**. At present, the only **<code>HintProviders</code>** in Kubernetes are the **<code>CPUManager</code>** and the **<code>DeviceManager</code>**. We plan to add support for **<code>HugePages</code>** soon.
|
||||
|
||||
As discussed previously, the **<code>TopologyManager</code>** both gathers **<code>TopologyHints</code>** from **<code>HintProviders</code>** as well as triggers aligned resource allocations on them using a merged "best" hint. As such, **<code>HintProviders</code>** implement the following interface:
|
||||
|
||||
```
|
||||
type HintProvider interface {
|
||||
GetTopologyHints(*v1.Pod, *v1.Container) map[string][]TopologyHint
|
||||
Allocate(*v1.Pod, *v1.Container) error
|
||||
}
|
||||
```
|
||||
|
||||
Notice that the call to **<code>GetTopologyHints()</code>** returns a **<code>map[string][]TopologyHint</code>**. This allows a single **<code>HintProvider</code>** to provide hints for multiple resource types instead of just one. For example, the **<code>DeviceManager</code>** requires this in order to pass hints back for every resource type registered by its plugins.
|
||||
|
||||
As **<code>HintProviders</code>** generate their hints, they only consider how alignment could be satisfied for _currently_ available resources on the system. Any resources already allocated to other containers are not considered.
|
||||
|
||||
For example, consider the system in Figure 1, with the following two containers requesting resources from it:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><strong><code>Container0</code></strong>
|
||||
</td>
|
||||
<td align="center"><strong><code>Container1</code></strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
<pre>
|
||||
spec:
|
||||
containers:
|
||||
- name: numa-aligned-container0
|
||||
image: alpine
|
||||
resources:
|
||||
limits:
|
||||
cpu: 2
|
||||
memory: 200Mi
|
||||
gpu-vendor.com/gpu: 1
|
||||
nic-vendor.com/nic: 1
|
||||
</pre>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<pre>
|
||||
spec:
|
||||
containers:
|
||||
- name: numa-aligned-container1
|
||||
image: alpine
|
||||
resources:
|
||||
limits:
|
||||
cpu: 2
|
||||
memory: 200Mi
|
||||
gpu-vendor.com/gpu: 1
|
||||
nic-vendor.com/nic: 1
|
||||
</pre>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
If **<code>Container0</code>** is the first container considered for allocation on the system, the following set of hints will be generated for the three topology-aware resource types in the spec.
|
||||
|
||||
```
|
||||
cpu: {{01: True}, {10: True}, {11: False}}
|
||||
gpu-vendor.com/gpu: {{01: True}, {10: True}}
|
||||
nic-vendor.com/nic: {{01: True}, {10: True}}
|
||||
```
|
||||
|
||||
With a resulting aligned allocation of:
|
||||
|
||||
```
|
||||
{cpu: {0, 1}, gpu: 0, nic: 0}
|
||||
```
|
||||
|
||||
<p align="center">
|
||||
<img height="300" src="/images/blog/2020-03-25-kubernetes-1.18-release-announcement/numa-hint-provider1.png">
|
||||
</p>
|
||||
|
||||
|
||||
When considering **<code>Container1</code>** these resources are then presumed to be unavailable, and thus only the following set of hints will be generated:
|
||||
|
||||
```
|
||||
cpu: {{01: True}, {10: True}, {11: False}}
|
||||
gpu-vendor.com/gpu: {{10: True}}
|
||||
nic-vendor.com/nic: {{10: True}}
|
||||
```
|
||||
|
||||
With a resulting aligned allocation of:
|
||||
|
||||
|
||||
```
|
||||
{cpu: {4, 5}, gpu: 1, nic: 1}
|
||||
```
|
||||
|
||||
<p align="center">
|
||||
<img height="300" src="/images/blog/2020-03-25-kubernetes-1.18-release-announcement/numa-hint-provider2.png">
|
||||
</p>
|
||||
|
||||
|
||||
**NOTE:** Unlike the pseudocode provided at the beginning of this section, the call to **<code>Allocate()</code>** does not actually take a parameter for the merged "best" hint directly. Instead, the **<code>TopologyManager</code>** implements the following **<code>Store</code>** interface that **<code>HintProviders</code>** can query to retrieve the hint generated for a particular container once it has been generated:
|
||||
|
||||
```
|
||||
type Store interface {
|
||||
GetAffinity(podUID string, containerName string) TopologyHint
|
||||
}
|
||||
```
|
||||
|
||||
Separating this out into its own API call allows one to access this hint outside of the pod admission loop. This is useful for debugging as well as for reporting generated hints in tools such as **<code>kubectl</code>**(not yet available).
|
||||
|
||||
### Policy.Merge
|
||||
|
||||
The merge strategy defined by a given policy dictates how it combines the set of **<code>TopologyHints</code>** generated by all **<code>HintProviders</code>** into a single **<code>TopologyHint</code>** that can be used to inform aligned resource allocations.
|
||||
|
||||
The general merge strategy for all supported policies begins the same:
|
||||
|
||||
1. Take the cross-product of **<code>TopologyHints</code>** generated for each resource type
|
||||
1. For each entry in the cross-product, **<code>bitwise-and</code>** the NUMA affinities of each **<code>TopologyHint</code>** together. Set this as the NUMA affinity in a resulting "merged" hint.
|
||||
1. If all of the hints in an entry have **<code>Preferred</code>** set to **<code>True</code>** , set **<code>Preferred</code>** to **<code>True</code>** in the resulting "merged" hint.
|
||||
1. If even one of the hints in an entry has **<code>Preferred</code>** set to **<code>False</code>** , set **<code>Preferred</code>** to **<code>False</code>** in the resulting "merged" hint. Also set **<code>Preferred</code>** to **<code>False</code>** in the "merged" hint if its NUMA affinity contains all 0s.
|
||||
|
||||
Following the example from the previous section with hints for **<code>Container0</code>** generated as:
|
||||
|
||||
```
|
||||
cpu: {{01: True}, {10: True}, {11: False}}
|
||||
gpu-vendor.com/gpu: {{01: True}, {10: True}}
|
||||
nic-vendor.com/nic: {{01: True}, {10: True}}
|
||||
```
|
||||
|
||||
The above algorithm results in the following set of cross-product entries and "merged" hints:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center">cross-product entry
|
||||
<p>
|
||||
<strong><code>{cpu, gpu-vendor.com/gpu, nic-vendor.com/nic}</code></strong>
|
||||
</p>
|
||||
</td>
|
||||
<td align="center">"merged" hint
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<strong><code>{{01: True}, {01: True}, {01: True}}</code></strong>
|
||||
</td>
|
||||
<td align="center"><strong><code>{01: True}</code></strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<strong><code>{{01: True}, {01: True}, {10: True}}</code></strong>
|
||||
</td>
|
||||
<td align="center"><strong><code>{00: False}</code></strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<strong><code>{{01: True}, {10: True}, {01: True}}</code></strong>
|
||||
</td>
|
||||
<td align="center"><strong><code>{00: False}</code></strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<strong><code>{{01: True}, {10: True}, {10: True}}</code></strong>
|
||||
</td>
|
||||
<td align="center"><strong><code>{00: False}</code></strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<strong><code>{{10: True}, {01: True}, {01: True}}</code></strong>
|
||||
</td>
|
||||
<td align="center"><strong><code>{00: False}</code></strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<strong><code>{{10: True}, {01: True}, {10: True}}</code></strong>
|
||||
</td align="center">
|
||||
<td align="center"><strong><code>{00: False}</code></strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<strong><code>{{10: True}, {10: True}, {01: True}}</code></strong>
|
||||
</td>
|
||||
<td align="center"><strong><code>{00: False}</code></strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<strong><code>{{10: True}, {10: True}, {10: True}}</code></strong>
|
||||
</td>
|
||||
<td align="center"><strong><code>{01: True}</code></strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<strong><code>{{11: False}, {01: True}, {01: True}}</code></strong>
|
||||
</td>
|
||||
<td align="center"><strong><code>{01: False}</code></strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<strong><code>{{11: False}, {01: True}, {10: True}}</code></strong>
|
||||
</td>
|
||||
<td align="center"><strong><code>{00: False}</code></strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<strong><code>{{11: False}, {10: True}, {01: True}}</code></strong>
|
||||
</td>
|
||||
<td align="center"><strong><code>{00: False}</code></strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<strong><code>{{11: False}, {10: True}, {10: True}}</code></strong>
|
||||
</td>
|
||||
<td align="center"><strong><code>{10: False}</code></strong>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
Once this list of "merged" hints has been generated, it is the job of the specific **<code>TopologyManager</code>** policy in use to decide which one to consider as the "best" hint.
|
||||
|
||||
In general, this involves:
|
||||
|
||||
1. Sorting merged hints by their "narrowness". Narrowness is defined as the number of bits set in a hint’s NUMA affinity mask. The fewer bits set, the narrower the hint. For hints that have the same number of bits set in their NUMA affinity mask, the hint with the most low order bits set is considered narrower.
|
||||
1. Sorting merged hints by their **<code>Preferred</code>** field. Hints that have **<code>Preferred</code>** set to **<code>True</code>** are considered more likely candidates than hints with **<code>Preferred</code>** set to **<code>False</code>**.
|
||||
1. Selecting the narrowest hint with the best possible setting for **<code>Preferred</code>**.
|
||||
|
||||
In the case of the **<code>best-effort</code>** policy this algorithm will always result in _some_ hint being selected as the "best" hint and the pod being admitted. This "best" hint is then made available to **<code>HintProviders</code>** so they can make their resource allocations based on it.
|
||||
|
||||
However, in the case of the **<code>restricted</code>** and **<code>single-numa-node</code>** policies, any selected hint with **<code>Preferred</code>** set to **<code>False</code>** will be rejected immediately, causing pod admission to fail and no resources to be allocated. Moreover, the **<code>single-numa-node</code>** will also reject a selected hint that has more than one NUMA node set in its affinity mask.
|
||||
|
||||
In the example above, the pod would be admitted by all policies with a hint of **<code>{01: True}</code>**.
|
||||
|
||||
## Upcoming enhancements
|
||||
|
||||
While the 1.18 release and promotion to Beta brings along some great enhancements and fixes, there are still a number of limitations, described [here](https://kubernetes.io/docs/tasks/administer-cluster/topology-manager/#known-limitations). We are already underway working to address these limitations and more.
|
||||
|
||||
This section walks through the set of enhancements we plan to implement for the **<code>TopologyManager</code>** in the near future. This list is not exhaustive, but it gives a good idea of the direction we are moving in. It is ordered by the timeframe in which we expect to see each enhancement completed.
|
||||
|
||||
If you would like to get involved in helping with any of these enhancements, please [join the weekly Kubernetes SIG-node meetings](https://github.com/kubernetes/community/tree/master/sig-node) to learn more and become part of the community effort!
|
||||
|
||||
### Supporting device-specific constraints
|
||||
|
||||
Currently, NUMA affinity is the only constraint considered by the **<code>TopologyManager</code>** for resource alignment. Moreover, the only scalable extensions that can be made to a **<code>TopologyHint</code>** involve _node-level_ constraints, such as PCIe bus alignment across device types. It would be intractable to try and add any _device-specific_ constraints to this struct (e.g. the internal NVLINK topology among a set of GPU devices).
|
||||
|
||||
As such, we propose an extension to the device plugin interface that will allow a plugin to state its topology-aware allocation preferences, without having to expose any device-specific topology information to the kubelet. In this way, the **<code>TopologyManager</code>** can be restricted to only deal with common node-level topology constraints, while still having a way of incorporating device-specific topology constraints into its allocation decisions.
|
||||
|
||||
Details of this proposal can be found [here](https://github.com/kubernetes/enhancements/pull/1121), and should be available as soon as Kubernetes 1.19.
|
||||
|
||||
### NUMA alignment for hugepages
|
||||
|
||||
As stated previously, the only two **<code>HintProviders</code>** currently available to the **<code>TopologyManager</code>** are the **<code>CPUManager</code>** and the **<code>DeviceManager</code>**. However, work is currently underway to add support for hugepages as well. With the completion of this work, the **<code>TopologyManager</code>** will finally be able to allocate memory, hugepages, CPUs and PCI devices all on the same NUMA node.
|
||||
|
||||
A [KEP](https://github.com/kubernetes/enhancements/blob/253f1e5bdd121872d2d0f7020a5ac0365b229e30/keps/sig-node/20200203-memory-manager.md) for this work is currently under review, and a prototype is underway to get this feature implemented very soon.
|
||||
|
||||
|
||||
### Scheduler awareness
|
||||
|
||||
Currently, the **<code>TopologyManager</code>** acts as a Pod Admission controller. It is not directly involved in the scheduling decision of where a pod will be placed. Rather, when the kubernetes scheduler (or whatever scheduler is running in the deployment), places a pod on a node to run, the **<code>TopologyManager</code>** will decide if the pod should be "admitted" or "rejected". If the pod is rejected due to lack of available NUMA aligned resources, things can get a little interesting. This kubernetes [issue](https://github.com/kubernetes/kubernetes/issues/84869) highlights and discusses this situation well.
|
||||
|
||||
So how do we go about addressing this limitation? We have the [Kubernetes Scheduling Framework](https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/20180409-scheduling-framework.md) to the rescue! This framework provides a new set of plugin APIs that integrate with the existing Kubernetes Scheduler and allow scheduling features, such as NUMA alignment, to be implemented without having to resort to other, perhaps less appealing alternatives, including writing your own scheduler, or even worse, creating a fork to add your own scheduler secret sauce.
|
||||
|
||||
The details of how to implement these extensions for integration with the **<code>TopologyManager</code>** have not yet been worked out. We still need to answer questions like:
|
||||
|
||||
* Will we require duplicated logic to determine device affinity in the **<code>TopologyManager</code>** and the scheduler?
|
||||
* Do we need a new API to get **<code>TopologyHints</code>** from the **<code>TopologyManager</code>** to the scheduler plugin?
|
||||
|
||||
Work on this feature should begin in the next couple of months, so stay tuned!
|
||||
|
||||
|
||||
### Per-pod alignment policy
|
||||
|
||||
As stated previously, a single policy is applied to _all_ pods on a node via a global **<code>kubelet</code>** flag, rather than allowing users to select different policies on a pod-by-pod basis (or a container-by-container basis).
|
||||
|
||||
While we agree that this would be a great feature to have, there are quite a few hurdles that need to be overcome before it is achievable. The biggest hurdle being that this enhancement will require an API change to be able to express the desired alignment policy in either the Pod spec or its associated **<code>[RuntimeClass](https://kubernetes.io/docs/concepts/containers/runtime-class/)</code>**.
|
||||
|
||||
We are only now starting to have serious discussions around this feature, and it is still a few releases away, at the best, from being available.
|
||||
|
||||
## Conclusion
|
||||
|
||||
With the promotion of the **<code>TopologyManager</code>** to Beta in 1.18, we encourage everyone to give it a try and look forward to any feedback you may have. Many fixes and enhancements have been worked on in the past several releases, greatly improving the functionality and reliability of the **<code>TopologyManager</code>** and its **<code>HintProviders</code>**. While there are still a number of limitations, we have a set of enhancements planned to address them, and look forward to providing you with a number of new features in upcoming releases.
|
||||
|
||||
If you have ideas for additional enhancements or a desire for certain features, don’t hesitate to let us know. The team is always open to suggestions to enhance and improve the **<code>TopologyManager</code>**.
|
||||
|
||||
We hope you have found this blog informative and useful! Let us know if you have any questions or comments. And, happy deploying…..Align Up!
|
||||
|
||||
|
||||
<!-- Docs to Markdown version 1.0β20 -->
|
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
layout: blog
|
||||
title: Kubernetes 1.18 Feature Server-side Apply Beta 2
|
||||
date: 2020-04-01
|
||||
slug: Kubernetes-1.18-Feature-Server-side-Apply-Beta-2
|
||||
---
|
||||
|
||||
**Authors:** Antoine Pelisse (Google)
|
||||
|
||||
## What is Server-side Apply?
|
||||
Server-side Apply is an important effort to migrate “kubectl apply” to the apiserver. It was started in 2018 by the Apply working group.
|
||||
|
||||
The use of kubectl to declaratively apply resources has exposed the following challenges:
|
||||
|
||||
- One needs to use the kubectl go code, or they have to shell out to kubectl.
|
||||
|
||||
- Strategic merge-patch, the patch format used by kubectl, grew organically and was challenging to fix while maintaining compatibility with various api-server versions.
|
||||
|
||||
- Some features are hard to implement directly on the client, for example, unions.
|
||||
|
||||
|
||||
Server-side Apply is a new merging algorithm, as well as tracking of field ownership, running on the Kubernetes api-server. Server-side Apply enables new features like conflict detection, so the system knows when two actors are trying to edit the same field.
|
||||
|
||||
## How does it work, what’s managedFields?
|
||||
Server-side Apply works by keeping track of which actor of the system has changed each field of an object. It does so by diffing all updates to objects, and recording all the fields that have changed as well the time of the operation. All this information is stored in the managedFields in the metadata of objects. Since objects can have many fields, this field can be quite large.
|
||||
|
||||
When someone applies, we can then use the information stored within managedFields to report relevant conflicts and help the merge algorithm to do the right thing.
|
||||
|
||||
## Wasn’t it already Beta before 1.18?
|
||||
Yes, Server-side Apply has been Beta since 1.16, but it didn’t track the owner for fields associated with objects that had not been applied. This means that most objects didn’t have the managedFields metadata stored, and conflicts for these objects cannot be resolved. With Kubernetes 1.18, all new objects will have the managedFields attached to them and provide accurate information on conflicts.
|
||||
|
||||
## How do I use it?
|
||||
The most common way to use this is through kubectl: `kubectl apply --server-side`. This is likely to show conflicts with other actors, including client-side apply. When that happens, conflicts can be forced by using the `--force-conflicts` flag, which will grab the ownership for the fields that have changed.
|
||||
|
||||
## Current limitations
|
||||
We have two important limitations right now, especially with sub-resources. The first is that if you apply with a status, the status is going to be ignored. We are still going to try and acquire the fields, which may lead to invalid conflicts. The other is that we do not update the managedFields on some sub-resources, including scale, so you may not see information about a horizontal pod autoscaler changing the number of replicas.
|
||||
|
||||
## What’s next?
|
||||
We are working hard to improve the experience of using server-side apply with kubectl, and we are trying to make it the default. As part of that, we want to improve the migration from client-side to server-side.
|
||||
|
||||
## Can I help?
|
||||
Of course! The working-group apply is available on slack #wg-apply, through the [mailing list](https://groups.google.com/forum/#!forum/kubernetes-wg-apply) and we also meet every other Tuesday at 9.30 PT on Zoom. We have lots of exciting features to build and can use all sorts of help.
|
||||
|
||||
We would also like to use the opportunity to thank the hard work of all the contributors involved in making this new beta possible:
|
||||
|
||||
* Daniel Smith
|
||||
* Jenny Buckley
|
||||
* Joe Betz
|
||||
* Julian Modesto
|
||||
* Kevin Wiesmüller
|
||||
* Maria Ntalla
|
|
@ -0,0 +1,87 @@
|
|||
---
|
||||
layout: blog
|
||||
title: Improvements to the Ingress API in Kubernetes 1.18
|
||||
date: 2020-04-02
|
||||
slug: Improvements-to-the-Ingress-API-in-Kubernetes-1.18
|
||||
---
|
||||
|
||||
**Authors:** Rob Scott (Google), Christopher M Luciano (IBM)
|
||||
|
||||
The Ingress API in Kubernetes has enabled a large number of controllers to provide simple and powerful ways to manage inbound network traffic to Kubernetes workloads. In Kubernetes 1.18, we've made 3 significant additions to this API:
|
||||
|
||||
* A new `pathType` field that can specify how Ingress paths should be matched.
|
||||
* A new `IngressClass` resource that can specify how Ingresses should be implemented by controllers.
|
||||
* Support for wildcards in hostnames.
|
||||
|
||||
## Better Path Matching With Path Types
|
||||
The new concept of a path type allows you to specify how a path should be matched. There are three supported types:
|
||||
|
||||
* __ImplementationSpecific (default):__ With this path type, matching is up to the controller implementing the `IngressClass`. Implementations can treat this as a separate `pathType` or treat it identically to the `Prefix` or `Exact` path types.
|
||||
* __Exact:__ Matches the URL path exactly and with case sensitivity.
|
||||
* __Prefix:__ Matches based on a URL path prefix split by `/`. Matching is case sensitive and done on a path element by element basis.
|
||||
|
||||
## Extended Configuration With Ingress Classes
|
||||
The Ingress resource was designed with simplicity in mind, providing a simple set of fields that would be applicable in all use cases. Over time, as use cases evolved, implementations began to rely on a long list of custom annotations for further configuration. The new `IngressClass` resource provides a way to replace some of those annotations.
|
||||
|
||||
Each `IngressClass` specifies which controller should implement Ingresses of the class and can reference a custom resource with additional parameters.
|
||||
```yaml
|
||||
apiVersion: "networking.k8s.io/v1beta1"
|
||||
kind: "IngressClass"
|
||||
metadata:
|
||||
name: "external-lb"
|
||||
spec:
|
||||
controller: "example.com/ingress-controller"
|
||||
parameters:
|
||||
apiGroup: "k8s.example.com/v1alpha"
|
||||
kind: "IngressParameters"
|
||||
name: "external-lb"
|
||||
```
|
||||
|
||||
### Specifying the Class of an Ingress
|
||||
A new `ingressClassName` field has been added to the Ingress spec that is used to reference the `IngressClass` that should be used to implement this Ingress.
|
||||
|
||||
### Deprecating the Ingress Class Annotation
|
||||
Before the `IngressClass` resource was added in Kubernetes 1.18, a similar concept of Ingress class was often specified with a `kubernetes.io/ingress.class` annotation on the Ingress. Although this annotation was never formally defined, it was widely supported by Ingress controllers, and should now be considered formally deprecated.
|
||||
|
||||
### Setting a Default IngressClass
|
||||
It’s possible to mark a specific `IngressClass` as default in a cluster. Setting the
|
||||
`ingressclass.kubernetes.io/is-default-class` annotation to true on an
|
||||
IngressClass resource will ensure that new Ingresses without an `ingressClassName` specified will be assigned this default `IngressClass`.
|
||||
|
||||
## Support for Hostname Wildcards
|
||||
Many Ingress providers have supported wildcard hostname matching like `*.foo.com` matching `app1.foo.com`, but until now the spec assumed an exact FQDN match of the host. Hosts can now be precise matches (for example “`foo.bar.com`”) or a wildcard (for example “`*.foo.com`”). Precise matches require that the http host header matches the Host setting. Wildcard matches require the http host header is equal to the suffix of the wildcard rule.
|
||||
|
||||
| Host | Host header | Match? |
|
||||
| ----------- |-------------------| --------------------------------------------------|
|
||||
| `*.foo.com` | `bar.foo.com` | Matches based on shared suffix |
|
||||
| `*.foo.com` | `baz.bar.foo.com` | No match, wildcard only covers a single DNS label |
|
||||
| `*.foo.com` | `foo.com` | No match, wildcard only covers a single DNS label |
|
||||
|
||||
### Putting it All Together
|
||||
These new Ingress features allow for much more configurability. Here’s an example of an Ingress that makes use of pathType, `ingressClassName`, and a hostname wildcard:
|
||||
|
||||
```yaml
|
||||
apiVersion: "networking.k8s.io/v1beta1"
|
||||
kind: "Ingress"
|
||||
metadata:
|
||||
name: "example-ingress"
|
||||
spec:
|
||||
ingressClassName: "external-lb"
|
||||
rules:
|
||||
- host: "*.example.com"
|
||||
http:
|
||||
paths:
|
||||
- path: "/example"
|
||||
pathType: "Prefix"
|
||||
backend:
|
||||
serviceName: "example-service"
|
||||
servicePort: 80
|
||||
```
|
||||
|
||||
### Ingress Controller Support
|
||||
Since these features are new in Kubernetes 1.18, each Ingress controller implementation will need some time to develop support for these new features. Check the documentation for your preferred Ingress controllers to see when they will support this new functionality.
|
||||
|
||||
## The Future of Ingress
|
||||
The Ingress API is on pace to graduate from beta to a stable API in Kubernetes 1.19. It will continue to provide a simple way to manage inbound network traffic for Kubernetes workloads. This API has intentionally been kept simple and lightweight, but there has been a desire for greater configurability for more advanced use cases.
|
||||
|
||||
Work is currently underway on a new highly configurable set of APIs that will provide an alternative to Ingress in the future. These APIs are being referred to as the new “Service APIs”. They are not intended to replace any existing APIs, but instead provide a more configurable alternative for complex use cases. For more information, check out the [Service APIs repo on GitHub](http://github.com/kubernetes-sigs/service-apis).
|
|
@ -0,0 +1,84 @@
|
|||
---
|
||||
layout: blog
|
||||
title: "Introducing Windows CSI support alpha for Kubernetes"
|
||||
date: 2020-04-03
|
||||
slug: kubernetes-1-18-feature-windows-csi-support-alpha
|
||||
---
|
||||
**Authors:** Authors: Deep Debroy [Docker], Jing Xu [Google], Krishnakumar R (KK) [Microsoft]
|
||||
|
||||
<em>The alpha version of [CSI Proxy][csi-proxy] for Windows is being released with Kubernetes 1.18. CSI proxy enables CSI Drivers on Windows by allowing containers in Windows to perform privileged storage operations.</em>
|
||||
|
||||
## Background
|
||||
|
||||
Container Storage Interface (CSI) for Kubernetes went GA in the Kubernetes 1.13 release. CSI has become the standard for exposing block and file storage to containerized workloads on Container Orchestration systems (COs) like Kubernetes. It enables third-party storage providers to write and deploy plugins without the need to alter the core Kubernetes codebase. All new storage features will utilize CSI, therefore it is important to get CSI drivers to work on Windows.
|
||||
|
||||
A CSI driver in Kubernetes has two main components: a controller plugin and a node plugin. The controller plugin generally does not need direct access to the host and can perform all its operations through the Kubernetes API and external control plane services (e.g. cloud storage service). The node plugin, however, requires direct access to the host for making block devices and/or file systems available to the Kubernetes kubelet. This was previously not possible for containers on Windows. With the release of [CSIProxy][csi-proxy], CSI drivers can now perform storage operations on the node. This inturn enables containerized CSI Drivers to run on Windows.
|
||||
|
||||
## CSI support for Windows clusters
|
||||
|
||||
CSI drivers (e.g. AzureDisk, GCE PD, etc.) are recommended to be deployed as containers. CSI driver’s node plugin typically runs on every worker node in the cluster (as a DaemonSet). Node plugin containers need to run with elevated privileges to perform storage related operations. However, Windows currently does not support privileged containers. To solve this problem, [CSIProxy][csi-proxy] makes it so that node plugins can now be deployed as unprivileged pods and then use the proxy to perform privileged storage operations on the node.
|
||||
|
||||
## Node plugin interactions with CSIProxy
|
||||
|
||||
The design of the CSI proxy is captured in this [KEP][kep]. The following diagram depicts the interactions with the CSI node plugin and CSI proxy.
|
||||
|
||||
<p align="center">
|
||||
<img src="/images/blog/2020-04-03-Introducing-Windows-CSI-support-alpha-for-Kubernetes/CSIProxyOverview.png">
|
||||
</p>
|
||||
|
||||
The CSI proxy runs as a process directly on the host on every windows node - very similar to kubelet. The CSI code in kubelet interacts with the [node driver registrar][nd-reg] component and the CSI node plugin. The node driver registrar is a community maintained CSI project which handles the registration of vendor specific node plugins. The kubelet initiates CSI gRPC calls like NodeStageVolume/NodePublishVolume on the node plugin as described in the figure. Node plugins interface with the CSIProxy process to perform local host OS storage related operations such as creation/enumeration of volumes, mounting/unmounting, etc.
|
||||
|
||||
## CSI proxy architecture and implementation
|
||||
|
||||
<p align="center">
|
||||
<img src="/images/blog/2020-04-03-Introducing-Windows-CSI-support-alpha-for-Kubernetes/CSIProxyArchitecture.png">
|
||||
</p>
|
||||
|
||||
In the alpha release, CSIProxy supports the following API groups:
|
||||
1. Filesystem
|
||||
1. Disk
|
||||
1. Volume
|
||||
1. SMB
|
||||
|
||||
CSI proxy exposes each API group via a Windows named pipe. The communication is performed using gRPC over these pipes. The client library from the CSI proxy project uses these pipes to interact with the CSI proxy APIs. For example, the filesystem APIs are exposed via a pipe like <code>\\.\pipe\csi-proxy-filesystem-v1alpha1</code> and volume APIs under the <code>\\.\pipe\csi-proxy-volume-v1alpha1</code>, and so on.
|
||||
|
||||
From each API group service, the calls are routed to the host API layer. The host API calls into the host Windows OS by either Powershell or Go standard library calls. For example, when the filesystem API [Rmdir][rmdir] is called the API group service would decode the grpc structure [RmdirRequest][rmdir-req] and find the directory to be removed and call into the Host APIs layer. This would result in a call to [os.Remove][os-rem], a Go standard library call, to perform the remove operation.
|
||||
|
||||
## Control flow details
|
||||
|
||||
The following figure uses CSI call NodeStageVolume as an example to explain the interaction between kubelet, CSI plugin, and CSI proxy for provisioning a fresh volume. After the node plugin receives a CSI RPC call, it makes a few calls to CSIproxy accordingly. As a result of the NodeStageVolume call, first the required disk is identified using either of the Disk API calls: ListDiskLocations (in AzureDisk driver) or GetDiskNumberByName (in GCE PD driver). If the disk is not partitioned, then the PartitionDisk (Disk API group) is called. Subsequently, Volume API calls such as ListVolumesOnDisk, FormatVolume and MountVolume are called to perform the rest of the required operations. Similar operations are performed in case of NodeUnstageVolume, NodePublishVolume, NodeUnpublishedVolume, etc.
|
||||
|
||||
<p align="center">
|
||||
<img src="/images/blog/2020-04-03-Introducing-Windows-CSI-support-alpha-for-Kubernetes/CSIProxyControlFlow.png">
|
||||
</p>
|
||||
|
||||
## Current support
|
||||
|
||||
CSI proxy is now available as alpha. You can find more details on the [CSIProxy][csi-proxy] GitHub repository. There are currently two cloud providers that provide alpha support for CSI drivers on Windows: Azure and GCE.
|
||||
|
||||
## Future plans
|
||||
|
||||
One key area of focus in beta is going to be Windows based build and CI/CD setup to improve the stability and quality of the code base. Another area is using Go based calls directly instead of Powershell commandlets to improve performance. Enhancing debuggability and adding more tests are other areas which the team will be looking into.
|
||||
|
||||
## How to get involved?
|
||||
|
||||
This project, like all of Kubernetes, is the result of hard work by many contributors from diverse backgrounds working together. Those interested in getting involved with the design and development of CSI Proxy, or any part of the Kubernetes Storage system, may join the [Kubernetes Storage Special Interest Group][sig] (SIG). We’re rapidly growing and always welcome new contributors.
|
||||
|
||||
For those interested in more details, the [CSIProxy][csi-proxy] GitHub repository is a good place to start. In addition, the [#csi-windows][slack] channel on kubernetes slack is available for discussions specific to the CSI on Windows.
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
We would like to thank Michelle Au for guiding us throughout this journey to alpha. We would like to thank Jean Rougé for contributions during the initial CSI proxy effort. We would like to thank Saad Ali for all the guidance with respect to the project and review/feedback on a draft of this blog. We would like to thank Patrick Lang and Mark Rossetti for helping us with Windows specific questions and details. Special thanks to Andy Zhang for reviews and guidance with respect to Azuredisk and Azurefile work. A big thank you to Paul Burt and Karen Chu for the review and suggestions on improving this blog post.
|
||||
|
||||
Last but not the least, we would like to thank the broader Kubernetes community who contributed at every step of the project.
|
||||
|
||||
|
||||
|
||||
[csi-proxy]: https://github.com/kubernetes-csi/csi-proxy
|
||||
[kep]: https://github.com/kubernetes/enhancements/blob/master/keps/sig-windows/20190714-windows-csi-support.md
|
||||
[nd-reg]: https://kubernetes-csi.github.io/docs/node-driver-registrar.html
|
||||
[rmdir]: https://github.com/kubernetes-csi/csi-proxy/blob/master/client/api/filesystem/v1alpha1/api.proto
|
||||
[rmdir-req]: https://github.com/kubernetes-csi/csi-proxy/blob/master/client/api/filesystem/v1alpha1/api.pb.go
|
||||
[os-rem]: https://github.com/kubernetes-csi/csi-proxy/blob/master/internal/os/filesystem/api.go
|
||||
[sig]: https://github.com/kubernetes/community/tree/master/sig-storage
|
||||
[slack]: https://kubernetes.slack.com/messages/csi-windows
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
layout: blog
|
||||
title: "API Priority and Fairness Alpha"
|
||||
date: 2020-04-06
|
||||
slug: kubernetes-1-18-feature-api-priority-and-fairness-alpha
|
||||
---
|
||||
|
||||
**Authors:** Min Kim (Ant Financial), Mike Spreitzer (IBM), Daniel Smith (Google)
|
||||
|
||||
This blog describes “API Priority And Fairness”, a new alpha feature in Kubernetes 1.18. API Priority And Fairness permits cluster administrators to divide the concurrency of the control plane into different weighted priority levels. Every request arriving at a kube-apiserver will be categorized into one of the priority levels and get its fair share of the control plane’s throughput.
|
||||
|
||||
## What problem does this solve?
|
||||
Today the apiserver has a simple mechanism for protecting itself against CPU and memory overloads: max-in-flight limits for mutating and for readonly requests. Apart from the distinction between mutating and readonly, no other distinctions are made among requests; consequently, there can be undesirable scenarios where one subset of the requests crowds out other requests.
|
||||
|
||||
In short, it is far too easy for Kubernetes workloads to accidentally DoS the apiservers, causing other important traffic--like system controllers or leader elections---to fail intermittently. In the worst cases, a few broken nodes or controllers can push a busy cluster over the edge, turning a local problem into a control plane outage.
|
||||
|
||||
## How do we solve the problem?
|
||||
The new feature “API Priority and Fairness” is about generalizing the existing max-in-flight request handler in each apiserver, to make the behavior more intelligent and configurable. The overall approach is as follows.
|
||||
|
||||
1. Each request is matched by a _Flow Schema_. The Flow Schema states the Priority Level for requests that match it, and assigns a “flow identifier” to these requests. Flow identifiers are how the system determines whether requests are from the same source or not.
|
||||
2. Priority Levels may be configured to behave in several ways. Each Priority Level gets its own isolated concurrency pool. Priority levels also introduce the concept of queuing requests that cannot be serviced immediately.
|
||||
3. To prevent any one user or namespace from monopolizing a Priority Level, they may be configured to have multiple queues. [“Shuffle Sharding”](https://aws.amazon.com/builders-library/workload-isolation-using-shuffle-sharding/#What_is_shuffle_sharding.3F) is used to assign each flow of requests to a subset of the queues.
|
||||
4. Finally, when there is capacity to service a request, a [“Fair Queuing”](https://en.wikipedia.org/wiki/Fair_queuing) algorithm is used to select the next request. Within each priority level the queues compete with even fairness.
|
||||
|
||||
Early results have been very promising! Take a look at this [analysis](https://github.com/kubernetes/kubernetes/pull/88177#issuecomment-588945806).
|
||||
|
||||
## How do I try this out?
|
||||
You are required to prepare the following things in order to try out the feature:
|
||||
|
||||
* Download and install a kubectl greater than v1.18.0 version
|
||||
* Enabling the new API groups with the command line flag `--runtime-config="flowcontrol.apiserver.k8s.io/v1alpha1=true"` on the kube-apiservers
|
||||
* Switch on the feature gate with the command line flag `--feature-gates=APIPriorityAndFairness=true` on the kube-apiservers
|
||||
|
||||
After successfully starting your kube-apiservers, you will see a few default FlowSchema and PriorityLevelConfiguration resources in the cluster. These default configurations are designed for a general protection and traffic management for your cluster.
|
||||
You can examine and customize the default configuration by running the usual tools, e.g.:
|
||||
|
||||
* `kubectl get flowschemas`
|
||||
* `kubectl get prioritylevelconfigurations`
|
||||
|
||||
|
||||
## How does this work under the hood?
|
||||
Upon arrival at the handler, a request is assigned to exactly one priority level and exactly one flow within that priority level. Hence understanding how FlowSchema and PriorityLevelConfiguration works will be helping you manage the request traffic going through your kube-apiservers.
|
||||
|
||||
* FlowSchema: FlowSchema will identify a PriorityLevelConfiguration object and the way to compute the request’s “flow identifier”. Currently we support matching requests according to: the identity making the request, the verb, and the target object. The identity can match in terms of: a username, a user group name, or a ServiceAccount. And as for the target objects, we can match by apiGroup, resource[/subresource], and namespace.
|
||||
* The flow identifier is used for shuffle sharding, so it’s important that requests have the same flow identifier if they are from the same source! We like to consider scenarios with “elephants” (which send many/heavy requests) vs “mice” (which send few/light requests): it is important to make sure the elephant’s requests all get the same flow identifier, otherwise they will look like many different mice to the system!
|
||||
* See the API Documentation [here](https://kubernetes.io/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#flowschema-v1alpha1-flowcontrol-apiserver-k8s-io)!
|
||||
|
||||
* PriorityLevelConfiguration: Defines a priority level.
|
||||
* For apiserver self requests, and any reentrant traffic (e.g., admission webhooks which themselves make API requests), a Priority Level can be marked “exempt”, which means that no queueing or limiting of any sort is done. This is to prevent priority inversions.
|
||||
* Each non-exempt Priority Level is configured with a number of "concurrency shares" and gets an isolated pool of concurrency to use. Requests of that Priority Level run in that pool when it is not full, never anywhere else. Each apiserver is configured with a total concurrency limit (taken to be the sum of the old limits on mutating and readonly requests), and this is then divided among the Priority Levels in proportion to their concurrency shares.
|
||||
* A non-exempt Priority Level may select a number of queues and a "hand size" to use for the shuffle sharding. Shuffle sharding maps flows to queues in a way that is better than consistent hashing. A given flow has access to a small collection of queues, and for each incoming request the shortest queue is chosen. When a Priority Level has queues, it also sets a limit on queue length. There is also a limit placed on how long a request can wait in its queue; this is a fixed fraction of the apiserver's request timeout. A request that cannot be executed and cannot be queued (any longer) is rejected.
|
||||
* Alternatively, a non-exempt Priority Level may select immediate rejection instead of waiting in a queue.
|
||||
* See the [API documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#prioritylevelconfiguration-v1alpha1-flowcontrol-apiserver-k8s-io) for this feature.
|
||||
|
||||
## What’s missing? When will there be a beta?
|
||||
We’re already planning a few enhancements based on alpha and there will be more as users send feedback to our community. Here’s a list of them:
|
||||
|
||||
* Traffic management for WATCH and EXEC requests
|
||||
* Adjusting and improving the default set of FlowSchema/PriorityLevelConfiguration
|
||||
* Enhancing observability on how this feature works
|
||||
* Join the discussion [here](https://github.com/kubernetes/enhancements/pull/1632)
|
||||
|
||||
Possibly treat LIST requests differently depending on an estimate of how big their result will be.
|
||||
|
||||
## How can I get involved?
|
||||
As always! Reach us on slack [#sig-api-machinery](https://kubernetes.slack.com/messages/sig-api-machinery), or through the [mailing list](https://groups.google.com/forum/#!forum/kubernetes-sig-api-machinery). We have lots of exciting features to build and can use all sorts of help.
|
||||
|
||||
Many thanks to the contributors that have gotten this feature this far: Aaron Prindle, Daniel Smith, Jonathan Tomer, Mike Spreitzer, Min Kim, Bruce Ma, Yu Liao, Mengyi Zhou!
|
|
@ -0,0 +1,222 @@
|
|||
---
|
||||
layout: blog
|
||||
title: "Cluster API v1alpha3 Delivers New Features and an Improved User Experience"
|
||||
date: 2020-04-21
|
||||
slug: cluster-api-v1alpha3-delivers-new-features-and-an-improved-user-experience
|
||||
---
|
||||
|
||||
**Author:** Daniel Lipovetsky (D2IQ)
|
||||
|
||||
<img src="/images/blog/2020-04-21-Cluster-API-v1alpha3-Delivers-New-Features-and-an-Improved-User-Experience/kubernetes-cluster-logos_final-02.svg" align="right" width="25%" alt="Cluster API Logo: Turtles All The Way Down">
|
||||
|
||||
The Cluster API is a Kubernetes project to bring declarative, Kubernetes-style APIs to cluster creation, configuration, and management. It provides optional, additive functionality on top of core Kubernetes to manage the lifecycle of a Kubernetes cluster.
|
||||
|
||||
Following the v1alpha2 release in October 2019, many members of the Cluster API community met in San Francisco, California, to plan the next release. The project had just gone through a major transformation, delivering a new architecture that promised to make the project easier for users to adopt, and faster for the community to build. Over the course of those two days, we found our common goals: To implement the features critical to managing production clusters, to make its user experience more intuitive, and to make it a joy to develop.
|
||||
|
||||
The v1alpha3 release of Cluster API brings significant features for anyone running Kubernetes in production and at scale. Among the highlights:
|
||||
|
||||
* [Declarative Control Plane Management](#declarative-control-plane-management)
|
||||
* [Support for Distributing Control Plane Nodes Across Failure Domains To Reduce Risk](#distributing-control-plane-nodes-to-reduce-risk)
|
||||
* [Automated Replacement of Unhealthy Nodes](#automated-replacement-of-unhealthy-nodes)
|
||||
* [Support for Infrastructure-Managed Node Groups](#infrastructure-managed-node-groups)
|
||||
|
||||
For anyone who wants to understand the API, or prizes a simple, but powerful, command-line interface, the new release brings:
|
||||
|
||||
* [Redesigned clusterctl, a command-line tool (and go library) for installing and managing the lifecycle of Cluster API](#clusterctl)
|
||||
* [Extensive and up-to-date documentation in The Cluster API Book](#the-cluster-api-book)
|
||||
|
||||
Finally, for anyone extending the Cluster API for their custom infrastructure or software needs:
|
||||
|
||||
* [New End-to-End (e2e) Test Framework](#end-to-end-test-framework)
|
||||
* [Documentation for integrating Cluster API into your cluster lifecycle stack](#provider-implementer-s-guide)
|
||||
|
||||
All this was possible thanks to the hard work of many contributors.
|
||||
|
||||
## Declarative Control Plane Management
|
||||
_Special thanks to [Jason DeTiberus](https://github.com/detiber/), [Naadir Jeewa](https://github.com/randomvariable), and [Chuck Ha](https://github.com/chuckha)_
|
||||
|
||||
The Kubeadm-based Control Plane (KCP) provides a declarative API to deploy and scale the Kubernetes control plane, including etcd. This is the feature many Cluster API users have been waiting for! Until now, to deploy and scale up the control plane, users had to create specially-crafted Machine resources. To scale down the control plane, they had to manually remove members from the etcd cluster. KCP automates deployment, scaling, and upgrades.
|
||||
|
||||
> **What is the Kubernetes Control Plane?**
|
||||
> The Kubernetes control plane is, at its core, kube-apiserver and etcd. If either of these are unavailable, no API requests can be handled. This impacts not only core Kubernetes APIs, but APIs implemented with CRDs. Other components, like kube-scheduler and kube-controller-manager, are also important, but do not have the same impact on availability.
|
||||
>
|
||||
> The control plane was important in the beginning because it scheduled workloads. However, some workloads could continue to run during a control plane outage. Today, workloads depend on operators, service meshes, and API gateways, which all use the control plane as a platform. Therefore, the control plane's availability is more important than ever.
|
||||
>
|
||||
> Managing the control plane is one of the most complex parts of cluster operation. Because the typical control plane includes etcd, it is stateful, and operations must be done in the correct sequence. Control plane replicas can and do fail, and maintaining control plane availability means being able to replace failed nodes.
|
||||
>
|
||||
> The control plane can suffer a complete outage (e.g. permanent loss of quorum in etcd), and recovery (along with regular backups) is sometimes the only feasible option.
|
||||
>
|
||||
> For more details, read about [Kubernetes Components](https://kubernetes.io/docs/concepts/overview/components/) in the Kubernetes documentation.
|
||||
|
||||
Here's an example of a 3-replica control plane for the Cluster API Docker Infrastructure, which the project maintains for testing and development. For brevity, other required resources, like Cluster, and Infrastructure Template, referenced by its name and namespace, are not shown.
|
||||
|
||||
```yaml
|
||||
apiVersion: controlplane.cluster.x-k8s.io/v1alpha3
|
||||
kind: KubeadmControlPlane
|
||||
metadata:
|
||||
name: example
|
||||
spec:
|
||||
infrastructureTemplate:
|
||||
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3
|
||||
kind: DockerMachineTemplate
|
||||
name: example
|
||||
namespace: default
|
||||
kubeadmConfigSpec:
|
||||
clusterConfiguration:
|
||||
replicas: 3
|
||||
version: 1.16.3
|
||||
```
|
||||
|
||||
Deploy this control plane with kubectl:
|
||||
```shell
|
||||
kubectl apply -f example-docker-control-plane.yaml
|
||||
```
|
||||
|
||||
Scale the control plane the same way you scale other Kubernetes resources:
|
||||
```shell
|
||||
kubectl scale kubeadmcontrolplane example --replicas=5
|
||||
```
|
||||
```
|
||||
kubeadmcontrolplane.controlplane.cluster.x-k8s.io/example scaled
|
||||
```
|
||||
|
||||
Upgrade the control plane to a newer patch of the Kubernetes release:
|
||||
```shell
|
||||
kubectl patch kubeadmcontrolplane example --type=json -p '[{"op": "replace", "path": "/spec/version", "value": "1.16.4"}]'
|
||||
```
|
||||
|
||||
> **Number of Control Plane Replicas**
|
||||
> By default, KCP is configured to manage etcd, and requires an odd number of replicas. If KCP is configured to not manage etcd, an odd number is recommended, but not required. An odd number of replicas ensures optimal etcd configuration. To learn why your etcd cluster should have an odd number of members, see the [etcd FAQ](https://etcd.io/docs/v3.4.0/faq/#why-an-odd-number-of-cluster-members).
|
||||
|
||||
Because it is a core Cluster API component, KCP can be used with any v1alpha3-compatible Infrastructure Provider that provides a fixed control plane endpoint, i.e., a load balancer or virtual IP. This endpoint enables requests to reach multiple control plane replicas.
|
||||
|
||||
> **What is an Infrastructure Provider?**
|
||||
> A source of computational resources (e.g. machines, networking, etc.). The community maintains providers for AWS, Azure, Google Cloud, and VMWare. For details, see the [list of providers](https://cluster-api.sigs.k8s.io/reference/providers.html) in the Cluster API Book.
|
||||
|
||||
## Distributing Control Plane Nodes To Reduce Risk
|
||||
_Special thanks to [Vince Prignano](https://github.com/vincepri/), and [Chuck Ha](https://github.com/chuckha)_
|
||||
|
||||
Cluster API users can now deploy nodes in different failure domains, reducing the risk of a cluster failing due to a domain outage. This is especially important for the control plane: If nodes in one domain fail, the cluster can continue to operate as long as the control plane is available to nodes in other domains.
|
||||
|
||||
> **What is a Failure Domain?**
|
||||
> A failure domain is a way to group the resources that would be made unavailable by some failure. For example, in many public clouds, an "availability zone" is the default failure domain. A zone corresponds to a data center. So, if a specific data center is brought down by a power outage or natural disaster, all resources in that zone become unavailable. If you run Kubernetes on your own hardware, your failure domain might be a rack, a network switch, or power distribution unit.
|
||||
|
||||
The Kubeadm-based ControlPlane distributes nodes across failure domains. To minimize the chance of losing multiple nodes in the event of a domain outage, it tries to distribute them evenly: it deploys a new node in the failure domain with the fewest existing nodes, and it removes an existing node in the failure domain with the most existing nodes.
|
||||
|
||||
MachineDeployments and MachineSets do not distribute nodes across failure domains. To deploy your worker nodes across multiple failure domains, create a MachineDeployment or MachineSet for each failure domain.
|
||||
|
||||
The Failure Domain API works on any infrastructure. That's because every Infrastructure Provider maps failure domains in its own way. The API is optional, so if your infrastructure is not complex enough to need failure domains, you do not need to support it. This example is for the Cluster API Docker Infrastructure Provider. Note that two of the domains are marked as suitable for control plane nodes, while a third is not. The Kubeadm-based ControlPlane will only deploy nodes to domains marked suitable.
|
||||
|
||||
```yaml
|
||||
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3
|
||||
kind: DockerCluster
|
||||
metadata:
|
||||
name: example
|
||||
spec:
|
||||
controlPlaneEndpoint:
|
||||
host: 172.17.0.4
|
||||
port: 6443
|
||||
failureDomains:
|
||||
domain-one:
|
||||
controlPlane: true
|
||||
domain-two:
|
||||
controlPlane: true
|
||||
domain-three:
|
||||
controlPlane: false
|
||||
```
|
||||
|
||||
The [AWS Infrastructure Provider](https://github.com/kubernetes-sigs/cluster-api-provider-aws) (CAPA), maintained by the Cluster API project, maps failure domains to AWS Availability Zones. Using CAPA, you can deploy a cluster across multiple Availability Zones. First, define subnets for multiple Availability Zones. The CAPA controller will define a failure domain for each Availability Zone. Deploy the control plane with the KubeadmControlPlane: it will distribute replicas across the failure domains. Finally, create a separate MachineDeployment for each failure domain.
|
||||
|
||||
## Automated Replacement of Unhealthy Nodes
|
||||
_Special thanks to [Alberto García Lamela](https://github.com/enxebre), and [Joel Speed](http://github.com/joelspeed)_
|
||||
|
||||
There are many reasons why a node might be unhealthy. The kubelet process may stop. The container runtime might have a bug. The kernel might have a memory leak. The disk may run out of space. CPU, disk, or memory hardware may fail. A power outage may happen. Failures like these are especially common in larger clusters.
|
||||
|
||||
Kubernetes is designed to tolerate them, and to help your applications tolerate them as well. Nevertheless, only a finite number of nodes can be unhealthy before the cluster runs out of resources, and Pods are evicted or not scheduled in the first place. Unhealthy nodes should be repaired or replaced at the earliest opportunity.
|
||||
|
||||
The Cluster API now includes a MachineHealthCheck resource, and a controller that monitors node health. When it detects an unhealthy node, it removes it. (Another Cluster API controller detects the node has been removed and replaces it.) You can configure the controller to suit your needs. You can configure how long to wait before removing the node. You can also set a threshold for the number of unhealthy nodes. When the threshold is reached, no more nodes are removed. The wait can be used to tolerate short-lived outages, and the threshold to prevent too many nodes from being replaced at the same time.
|
||||
|
||||
The controller will remove only nodes managed by a Cluster API MachineSet. The controller does not remove control plane nodes, whether managed by the Kubeadm-based Control Plane, or by the user, as in v1alpha2. For more, see [Limits and Caveats of a MachineHealthCheck](https://cluster-api.sigs.k8s.io/tasks/healthcheck.html#limitations-and-caveats-of-a-machinehealthcheck).
|
||||
|
||||
Here is an example of a MachineHealthCheck. For more details, see [Configure a MachineHealthCheck](https://cluster-api.sigs.k8s.io/tasks/healthcheck.html) in the Cluster API book.
|
||||
|
||||
```yaml
|
||||
apiVersion: cluster.x-k8s.io/v1alpha3
|
||||
kind: MachineHealthCheck
|
||||
metadata:
|
||||
name: example-node-unhealthy-5m
|
||||
spec:
|
||||
clusterName: example
|
||||
maxUnhealthy: 33%
|
||||
nodeStartupTimeout: 10m
|
||||
selector:
|
||||
matchLabels:
|
||||
nodepool: nodepool-0
|
||||
unhealthyConditions:
|
||||
- type: Ready
|
||||
status: Unknown
|
||||
timeout: 300s
|
||||
- type: Ready
|
||||
status: "False"
|
||||
timeout: 300s
|
||||
```
|
||||
|
||||
## Infrastructure-Managed Node Groups
|
||||
_Special thanks to [Juan-Lee Pang](https://github.com/juan-lee) and [Cecile Robert-Michon](https://github.com/CecileRobertMichon)_
|
||||
|
||||
If you run large clusters, you need to create and destroy hundreds of nodes, sometimes in minutes. Although public clouds make it possible to work with large numbers of nodes, having to make a separate API request to create or delete every node may scale poorly. For example, API requests may have to be delayed to stay within rate limits.
|
||||
|
||||
Some public clouds offer APIs to manage groups of nodes as one single entity. For example, AWS has AutoScaling Groups, Azure has Virtual Machine Scale Sets, and GCP has Managed Instance Groups. With this release of Cluster API, Infrastructure Providers can add support for these APIs, and users can deploy groups of Cluster API Machines by using the MachinePool Resource. For more information, see the [proposal](https://github.com/kubernetes-sigs/cluster-api/blob/bf51a2502f9007b531f6a9a2c1a4eae1586fb8ca/docs/proposals/20190919-machinepool-api.md) in the Cluster API repository.
|
||||
|
||||
> **Experimental Feature**
|
||||
> The MachinePool API is an experimental feature that is not enabled by default. Users are encouraged to try it and report on how well it meets their needs.
|
||||
|
||||
## The Cluster API User Experience, Reimagined
|
||||
|
||||
### clusterctl
|
||||
_Special thanks to [Fabrizio Pandini](https://github.com/fabriziopandini)_
|
||||
|
||||
If you are new to Cluster API, your first experience will probably be with the project's command-line tool, clusterctl. And with the new Cluster API release, it has been re-designed to be more pleasing to use than before. The tool is all you need to deploy your first [workload cluster](https://cluster-api.sigs.k8s.io/reference/glossary.html?highlight=pool#workload-cluster) in just a few steps.
|
||||
|
||||
First, use `clusterctl init` to [fetch the configuration](https://cluster-api.sigs.k8s.io/clusterctl/commands/init.html) for your Infrastructure and Bootstrap Providers and deploy all of the components that make up the Cluster API. Second, use `clusterctl config cluster` to [create the workload cluster manifest](https://cluster-api.sigs.k8s.io/clusterctl/commands/config-cluster.html). This manifest is just a collection of Kubernetes objects. To create the workload cluster, just `kubectl apply` the manifest. Don't be surprised if this workflow looks familiar: Deploying a workload cluster with Cluster API is just like deploying an application workload with Kubernetes!
|
||||
|
||||
Clusterctl also helps with the "day 2" operations. Use `clusterctl move` to [migrate Cluster API custom resources](https://cluster-api.sigs.k8s.io/clusterctl/commands/move.html), such as Clusters, and Machines, from one [Management Cluster](https://cluster-api.sigs.k8s.io/reference/glossary.html#management-cluster) to another. This step--also known as a [pivot](https://cluster-api.sigs.k8s.io/reference/glossary.html#pivot)--is necessary to create a workload cluster that manages itself with Cluster API. Finally, use `clusterctl upgrade` to [upgrade all of the installed components](https://cluster-api.sigs.k8s.io/clusterctl/commands/upgrade.html) when a new Cluster API release becomes available.
|
||||
|
||||
One more thing! Clusterctl is not only a command-line tool. It is also a Go library! Think of the library as an integration point for projects that build on top of Cluster API. All of clusterctl's command-line functionality is available in the library, making it easy to integrate into your stack. To get started with the library, please read its [documentation](https://pkg.go.dev/sigs.k8s.io/cluster-api@v0.3.1/cmd/clusterctl/client?tab=doc).
|
||||
|
||||
### The Cluster API Book
|
||||
_Thanks to many contributors!_
|
||||
|
||||
The [project's documentation](https://cluster-api.sigs.k8s.io/) is extensive. New users should get some background on the [architecture](https://cluster-api.sigs.k8s.io/user/concepts.html), and then create a cluster of their own with the [Quick Start](https://cluster-api.sigs.k8s.io/user/quick-start.html). The clusterctl tool has its own [reference](https://cluster-api.sigs.k8s.io/clusterctl/overview.html). The [Developer Guide](https://cluster-api.sigs.k8s.io/developer/guide.html) has plenty of information for anyone interested in contributing to the project.
|
||||
|
||||
Above and beyond the content itself, the project's documentation site is a pleasure to use. It is searchable, has an outline, and even supports different color themes. If you think the site a lot like the documentation for a different community project, [Kubebuilder](https://book.kubebuilder.io/), that is no coincidence! Many thanks to Kubebuilder authors for creating a great example of documentation. And many thanks to the [mdBook](https://github.com/rust-lang/mdBook) authors for creating a great tool for building documentation.
|
||||
|
||||
## Integrate & Customize
|
||||
|
||||
### End-to-End Test Framework
|
||||
_Special thanks to [Chuck Ha](https://github.com/chuckha)_
|
||||
|
||||
The Cluster API project is designed to be extensible. For example, anyone can develop their own Infrastructure and Bootstrap Providers. However, it's important that Providers work in a uniform way. And, because the project is still evolving, it takes work to make sure that Providers are up-to-date with new releases of the core.
|
||||
|
||||
The End-to-End Test Framework provides a set of standard tests for developers to verify that their Providers integrate correctly with the current release of Cluster API, and help identify any regressions that happen after a new release of the Cluster API, or the Provider.
|
||||
|
||||
For more details on the Framework, see [Testing](https://cluster-api.sigs.k8s.io/developer/testing.html?highlight=e2e#running-the-end-to-end-tests) in the Cluster API Book, and the [README](https://github.com/kubernetes-sigs/cluster-api/tree/master/test/framework) in the repository.
|
||||
|
||||
### Provider Implementer's Guide
|
||||
_Thanks to many contributors!_
|
||||
|
||||
The community maintains [Infrastructure Providers](https://cluster-api.sigs.k8s.io/reference/providers.html) for a many popular infrastructures. However, if you want to build your own Infrastructure or Bootstrap Provider, the [Provider Implementer's](https://cluster-api.sigs.k8s.io/developer/providers/implementers-guide/overview.html) guide explains the entire process, from creating a git repository, to creating CustomResourceDefinitions for your Providers, to designing, implementing, and testing the controllers.
|
||||
|
||||
> **Under Active Development**
|
||||
> The Provider Implementer's Guide is actively under development, and may not yet reflect all of the changes in the v1alpha3 release.
|
||||
|
||||
## Join Us!
|
||||
|
||||
The Cluster API project is a very active project, and covers many areas of interest. If you are an infrastructure expert, you can contribute to one of the Infrastructure Providers. If you like building controllers, you will find opportunities to innovate. If you're curious about testing distributed systems, you can help develop the project's end-to-end test framework. Whatever your interests and background, you can make a real impact on the project.
|
||||
|
||||
Come introduce yourself to the community at our weekly meeting, where we dedicate a block of time for a Q&A session. You can also find maintainers and users on the Kubernetes Slack, and in the Kubernetes forum. Please check out the links below. We look forward to seeing you!
|
||||
|
||||
* Chat with us on the Kubernetes [Slack](http://slack.k8s.io/):[ #cluster-api](https://kubernetes.slack.com/archives/C8TSNPY4T)
|
||||
* Join the [sig-cluster-lifecycle](https://groups.google.com/forum/) Google Group to receive calendar invites and gain access to documents
|
||||
* Join our [Zoom meeting](https://zoom.us/j/861487554), every Wednesday at 10:00 Pacific Time
|
||||
* Post to the [Cluster API community forum](https://discuss.kubernetes.io/c/contributors/cluster-api)
|
|
@ -0,0 +1,127 @@
|
|||
---
|
||||
layout: blog
|
||||
title: How Kubernetes contributors are building a better communication process
|
||||
date: 2020-04-21
|
||||
slug: contributor-communication
|
||||
---
|
||||
|
||||
**Authors:** Paris Pittman
|
||||
|
||||
> "Perhaps we just need to use a different word. We may need to use community development or project advocacy as a word in the open source realm as opposed to marketing, and perhaps then people will realize that they need to do it."
|
||||
> ~ [*Nithya Ruff*](https://todogroup.org/www.linkedin.com/in/nithyaruff/) (from [*TODO Group*](https://todogroup.org/guides/marketing-open-source-projects/))
|
||||
|
||||
A common way to participate in the Kubernetes contributor community is
|
||||
to be everywhere.
|
||||
|
||||
We have an active [Slack](https://slack.k8s.io), many mailing lists, Twitter account(s), and
|
||||
dozens of community-driven podcasts and newsletters that highlight all
|
||||
end-user, contributor, and ecosystem topics. And to add on to that, we also have [repositories of amazing documentation], tons of [meetings] that drive the project forward, and [recorded code deep dives]. All of this information is incredibly valuable,
|
||||
but it can be too much.
|
||||
|
||||
Keeping up with thousands of contributors can be a challenge for anyone,
|
||||
but this task of consuming information straight from the firehose is
|
||||
particularly challenging for new community members. It's no secret that
|
||||
the project is vast for contributors and users alike.
|
||||
|
||||
To paint a picture with numbers:
|
||||
|
||||
- 43,000 contributors
|
||||
- 6,579 members in #kubernetes-dev slack channel
|
||||
- 52 mailing lists (kubernetes-dev@ has thousands of members; sig-networking@ has 1000 alone)
|
||||
- 40 [community groups](https://github.com/kubernetes/community/blob/master/governance.md#community-groups)
|
||||
- 30 [upstream meetings](https://calendar.google.com/calendar/embed?src=cgnt364vd8s86hr2phapfjc6uk%40group.calendar.google.com&ctz=America%2FLos_Angeles) *this* week alone
|
||||
|
||||
All of these numbers are only growing in scale, and with that comes the need to simplify how contributors get the information right information front-and-center.
|
||||
|
||||
## How we got here
|
||||
|
||||
Kubernetes (K8s for short) communication grew out of a need for people
|
||||
to connect in our growing community. With the best of intentions, the
|
||||
community spun up channels for people to connect. This energy was part
|
||||
of what helped Kubernetes grow so fast, and it also had us in sprawling out far and wide. As adoption grew, [contributors knew there was a need for standardization](https://github.com/kubernetes/community/issues/2466).
|
||||
|
||||
This new attention to how the community communicates led to the discovery
|
||||
of a complex web of options. There were so many options, and it was a
|
||||
challenge for anyone to be sure they were in the right place to receive
|
||||
the right information. We started taking immediate action combining communication streams and thinking about how to reach out best to serve our community. We also asked for feedback from all our
|
||||
contributors directly via [**annual surveys**](https://github.com/kubernetes/community/tree/master/sig-contributor-experience/surveys)
|
||||
to see where folks were actually reading the news that influences their
|
||||
experiences here in our community.
|
||||
|
||||
![Kubernetes channel access](https://user-images.githubusercontent.com/1744971/79478603-3a3a1980-7fd1-11ea-8b7a-d36aac7a097b.png)
|
||||
|
||||
With over 43,000 contributors, our contributor base is larger than many enterprise companies. You can imagine what it's like getting important messages across to make sure they are landing and folks are taking action.
|
||||
|
||||
## Contributing to better communication
|
||||
|
||||
Think about how your company/employer solves for this kind of communication challenge. Many have done so
|
||||
by building internal marketing and communication focus areas in
|
||||
marketing departments. So that's what we are doing. This has also been
|
||||
applied [at Fedora](https://fedoraproject.org/wiki/Marketing) and at a smaller
|
||||
scale in our very [own release](https://github.com/kubernetes/sig-release/tree/master/release-team) and [contributor summit](https://github.com/kubernetes/community/blob/d0fd6c16f7ee754b08082cc15658eb8db7afeaf8/events/events-team/marketing/README.md) planning
|
||||
teams as roles.
|
||||
|
||||
We have hit the accelerator on an **upstream marketing group** under SIG
|
||||
Contributor Experience and we want to tackle this challenge straight on.
|
||||
We've learned in other contributor areas that creating roles for
|
||||
contributors is super helpful - onboarding, breaking down work, and
|
||||
ownership. [Here's our team charting the course](https://github.com/kubernetes/community/tree/master/communication/marketing-team).
|
||||
|
||||
Journey your way through our other documents like our [charter] if you are
|
||||
interested in our mission and scope.
|
||||
|
||||
Many of you close to the ecosystem might be scratching your head - isn't
|
||||
this what CNCF does?
|
||||
|
||||
Yes and no. The CNCF has 40+ other projects that need to be marketed to
|
||||
a countless number of different types of community members in distinct
|
||||
ways and they aren't responsible for the day to day operations of their
|
||||
projects. They absolutely do partner with us to highlight what we need
|
||||
and when we need it, and they do a fantastic job of it (one example is
|
||||
the [*@kubernetesio Twitter account*](https://twitter.com/kubernetesio) and its 200,000
|
||||
followers).
|
||||
|
||||
Where this group differs is in its scope: we are entirely
|
||||
focused on elevating the hard work being done throughout the Kubernetes
|
||||
community by its contributors.
|
||||
|
||||
## What to expect from us
|
||||
|
||||
You can expect to see us on the Kubernetes [communication channels](https://github.com/kubernetes/community/tree/master/communication) supporting you by:
|
||||
|
||||
- Finding ways of adding our human touch to potentially overwhelming
|
||||
quantities of info by storytelling and other methods - we want to
|
||||
highlight the work you are doing and provide useful information!
|
||||
- Keeping you in the know of the comings and goings of contributor
|
||||
community events, activities, mentoring initiatives, KEPs, and more.
|
||||
- Creating a presence on Twitter specifically for contributors via
|
||||
@k8scontributors that is all about being a contributor in all its
|
||||
forms.
|
||||
|
||||
What does this look like in the wild? Our [first post](https://kubernetes.io/blog/2020/03/19/join-sig-scalability/) in a series about our 36 community groups landed recently. Did you see it?
|
||||
More articles like this and additional themes of stories to flow through
|
||||
[our storytellers](https://github.com/kubernetes/community/tree/master/communication/marketing-team#purpose).
|
||||
|
||||
We will deliver this with an [ethos](https://github.com/kubernetes/community/blob/master/communication/marketing-team/CHARTER.md#ethosvision) behind us aligned to the Kubernetes project as a whole, and we're
|
||||
committed to using the same tools as all the other SIGs to do so. Check out our [project board](https://github.com/orgs/kubernetes/projects/39) to view our roadmap of upcoming work.
|
||||
|
||||
## Join us and be part of the story
|
||||
|
||||
This initiative is in an early phase and we still have important roles to fill to make it successful.
|
||||
|
||||
If you are interested in open sourcing marketing functions – it's a fun
|
||||
ride – join us! Specific immediate roles include storytelling through
|
||||
blogs and as a designer. We also have plenty of work in progress on our project board.
|
||||
Add a comment to any open issue to let us know you're interested in getting involved.
|
||||
|
||||
Also, if you're reading this, you're exactly the type of person we are
|
||||
here to support. We would love to hear about how to improve, feedback,
|
||||
or how we can work together.
|
||||
|
||||
Reach out at one of the contact methods listed on [our README](https://github.com/kubernetes/community/tree/master/communication/marketing-team#contact-us). We would love to hear from you.
|
||||
|
||||
|
||||
[repositories of amazing documentation]: http://github.com/kubernetes/community
|
||||
[meetings]: https://calendar.google.com/calendar/embed?src=cgnt364vd8s86hr2phapfjc6uk%40group.calendar.google.com&ctz=America%2FLos_Angeles
|
||||
[recorded code deep dives]: https://www.youtube.com/watch?v=yqB_le-N6EE
|
||||
[charter]: https://github.com/kubernetes/community/blob/master/communication/marketing-team/CHARTER.md
|
|
@ -0,0 +1,766 @@
|
|||
---
|
||||
title: "Two-phased Canary Rollout with Open Source Gloo"
|
||||
date: 2020-04-22
|
||||
slug: two-phased-canary-rollout-with-gloo
|
||||
url: /blog/2020/04/Two-phased-Canary-Rollout-With-Gloo
|
||||
---
|
||||
|
||||
**Author:** Rick Ducott | [GitHub](https://github.com/rickducott/) | [Twitter](https://twitter.com/ducott)
|
||||
|
||||
Every day, my colleagues and I are talking to platform owners, architects, and engineers who are using [Gloo](https://github.com/solo-io/gloo) as an API gateway
|
||||
to expose their applications to end users. These applications may span legacy monoliths, microservices, managed cloud services, and Kubernetes
|
||||
clusters. Fortunately, Gloo makes it easy to set up routes to manage, secure, and observe application traffic while
|
||||
supporting a flexible deployment architecture to meet the varying production needs of our users.
|
||||
|
||||
Beyond the initial set up, platform owners frequently ask us to help design the operational workflows within their organization:
|
||||
How do we bring a new application online? How do we upgrade an application? How do we divide responsibilities across our
|
||||
platform, ops, and development teams?
|
||||
|
||||
In this post, we're going to use Gloo to design a two-phased canary rollout workflow for application upgrades:
|
||||
|
||||
- In the first phase, we'll do canary testing by shifting a small subset of traffic to the new version. This allows you to safely perform smoke and correctness tests.
|
||||
- In the second phase, we'll progressively shift traffic to the new version, allowing us to monitor the new version under load, and eventually, decommission the old version.
|
||||
|
||||
To keep it simple, we're going to focus on designing the workflow using [open source Gloo](https://github.com/solo-io/gloo), and we're going to deploy the gateway and
|
||||
application to Kubernetes. At the end, we'll talk about a few extensions and advanced topics that could be interesting to explore in a follow up.
|
||||
|
||||
## Initial setup
|
||||
|
||||
To start, we need a Kubernetes cluster. This example doesn't take advantage of any cloud specific
|
||||
features, and can be run against a local test cluster such as [minikube](https://kubernetes.io/docs/tasks/tools/install-minikube/).
|
||||
This post assumes a basic understanding of Kubernetes and how to interact with it using `kubectl`.
|
||||
|
||||
We'll install the latest [open source Gloo](https://github.com/solo-io/gloo) to the `gloo-system` namespace and deploy
|
||||
version `v1` of an example application to the `echo` namespace. We'll expose this application outside the cluster
|
||||
by creating a route in Gloo, to end up with a picture like this:
|
||||
|
||||
![Setup](/images/blog/2020-04-22-two-phased-canary-rollout-with-gloo/setup.png)
|
||||
|
||||
### Deploying Gloo
|
||||
|
||||
We'll install gloo with the `glooctl` command line tool, which we can download and add to the `PATH` with the following
|
||||
commands:
|
||||
|
||||
```
|
||||
curl -sL https://run.solo.io/gloo/install | sh
|
||||
export PATH=$HOME/.gloo/bin:$PATH
|
||||
```
|
||||
|
||||
Now, you should be able to run `glooctl version` to see that it is installed correctly:
|
||||
|
||||
```
|
||||
➜ glooctl version
|
||||
Client: {"version":"1.3.15"}
|
||||
Server: version undefined, could not find any version of gloo running
|
||||
```
|
||||
|
||||
Now we can install the gateway to our cluster with a simple command:
|
||||
|
||||
```
|
||||
glooctl install gateway
|
||||
```
|
||||
|
||||
The console should indicate the install finishes successfully:
|
||||
|
||||
```
|
||||
Creating namespace gloo-system... Done.
|
||||
Starting Gloo installation...
|
||||
|
||||
Gloo was successfully installed!
|
||||
|
||||
```
|
||||
|
||||
Before long, we can see all the Gloo pods running in the `gloo-system` namespace:
|
||||
|
||||
```
|
||||
➜ kubectl get pod -n gloo-system
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
discovery-58f8856bd7-4fftg 1/1 Running 0 13s
|
||||
gateway-66f86bc8b4-n5crc 1/1 Running 0 13s
|
||||
gateway-proxy-5ff99b8679-tbp65 1/1 Running 0 13s
|
||||
gloo-66b8dc8868-z5c6r 1/1 Running 0 13s
|
||||
```
|
||||
|
||||
### Deploying the application
|
||||
|
||||
Our `echo` application is a simple container (thanks to our friends at HashiCorp) that will
|
||||
respond with the application version, to help demonstrate our canary workflows as we start testing and
|
||||
shifting traffic to a `v2` version of the application.
|
||||
|
||||
Kubernetes gives us a lot of flexibility in terms of modeling this application. We'll adopt the following
|
||||
conventions:
|
||||
|
||||
- We'll include the version in the deployment name so we can run two versions of the application
|
||||
side-by-side and manage their lifecycle differently.
|
||||
- We'll label pods with an app label (`app: echo`) and a version label (`version: v1`) to help with our canary rollout.
|
||||
- We'll deploy a single Kubernetes `Service` for the application to set up networking. Instead of updating
|
||||
this or using multiple services to manage routing to different versions, we'll manage the rollout with Gloo configuration.
|
||||
|
||||
The following is our `v1` echo application:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: echo-v1
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: echo
|
||||
version: v1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: echo
|
||||
version: v1
|
||||
spec:
|
||||
containers:
|
||||
# Shout out to our friends at Hashi for this useful test server
|
||||
- image: hashicorp/http-echo
|
||||
args:
|
||||
- "-text=version:v1"
|
||||
- -listen=:8080
|
||||
imagePullPolicy: Always
|
||||
name: echo-v1
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
```
|
||||
|
||||
And here is the `echo` Kubernetes `Service` object:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: echo
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: echo
|
||||
```
|
||||
|
||||
For convenience, we've published this yaml in a repo so we can deploy it with the following command:
|
||||
|
||||
```
|
||||
kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo-ref-arch/blog-30-mar-20/platform/prog-delivery/two-phased-with-os-gloo/1-setup/echo.yaml
|
||||
```
|
||||
|
||||
We should see the following output:
|
||||
|
||||
```
|
||||
namespace/echo created
|
||||
deployment.apps/echo-v1 created
|
||||
service/echo created
|
||||
```
|
||||
|
||||
And we should be able to see all the resources healthy in the `echo` namespace:
|
||||
|
||||
```
|
||||
➜ kubectl get all -n echo
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
pod/echo-v1-66dbfffb79-287s5 1/1 Running 0 6s
|
||||
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/echo ClusterIP 10.55.252.216 <none> 80/TCP 6s
|
||||
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
deployment.apps/echo-v1 1/1 1 1 7s
|
||||
|
||||
NAME DESIRED CURRENT READY AGE
|
||||
replicaset.apps/echo-v1-66dbfffb79 1 1 1 7s
|
||||
```
|
||||
|
||||
### Exposing outside the cluster with Gloo
|
||||
|
||||
We can now expose this service outside the cluster with Gloo. First, we'll model the application as a Gloo
|
||||
[Upstream](https://docs.solo.io/gloo/latest/introduction/architecture/concepts/#upstreams), which is Gloo's abstraction
|
||||
for a traffic destination:
|
||||
|
||||
```yaml
|
||||
apiVersion: gloo.solo.io/v1
|
||||
kind: Upstream
|
||||
metadata:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
spec:
|
||||
kube:
|
||||
selector:
|
||||
app: echo
|
||||
serviceName: echo
|
||||
serviceNamespace: echo
|
||||
servicePort: 8080
|
||||
subsetSpec:
|
||||
selectors:
|
||||
- keys:
|
||||
- version
|
||||
```
|
||||
|
||||
Here, we're setting up subsets based on the `version` label. We don't have to use this in our routes, but later
|
||||
we'll start to use it to support our canary workflow.
|
||||
|
||||
We can now create a route to this upstream in Gloo by defining a
|
||||
[Virtual Service](https://docs.solo.io/gloo/latest/introduction/architecture/concepts/#virtual-services):
|
||||
|
||||
```yaml
|
||||
apiVersion: gateway.solo.io/v1
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
spec:
|
||||
virtualHost:
|
||||
domains:
|
||||
- "*"
|
||||
routes:
|
||||
- matchers:
|
||||
- prefix: /
|
||||
routeAction:
|
||||
single:
|
||||
upstream:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
```
|
||||
|
||||
We can apply these resources with the following commands:
|
||||
|
||||
```
|
||||
kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo-ref-arch/blog-30-mar-20/platform/prog-delivery/two-phased-with-os-gloo/1-setup/upstream.yaml
|
||||
kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo-ref-arch/blog-30-mar-20/platform/prog-delivery/two-phased-with-os-gloo/1-setup/vs.yaml
|
||||
```
|
||||
|
||||
Once we apply these two resources, we can start to send traffic to the application through Gloo:
|
||||
|
||||
```
|
||||
➜ curl $(glooctl proxy url)/
|
||||
version:v1
|
||||
```
|
||||
|
||||
Our setup is complete, and our cluster now looks like this:
|
||||
|
||||
![Setup](/images/blog/2020-04-22-two-phased-canary-rollout-with-gloo/setup.png)
|
||||
|
||||
## Two-Phased Rollout Strategy
|
||||
|
||||
Now we have a new version `v2` of the echo application that we wish to roll out. We know that when the
|
||||
rollout is complete, we are going to end up with this picture:
|
||||
|
||||
![End State](/images/blog/2020-04-22-two-phased-canary-rollout-with-gloo/end-state.png)
|
||||
|
||||
However, to get there, we may want to perform a few rounds of testing to ensure the new version of the application
|
||||
meets certain correctness and/or performance acceptance criteria. In this post, we'll introduce a two-phased approach to
|
||||
canary rollout with Gloo, that could be used to satisfy the vast majority of acceptance tests.
|
||||
|
||||
In the first phase, we'll perform smoke and correctness tests by routing a small segment of the traffic to the new version
|
||||
of the application. In this demo, we'll use a header `stage: canary` to trigger routing to the new service, though in
|
||||
practice it may be desirable to make this decision based on another part of the request, such as a claim in a verified JWT.
|
||||
|
||||
In the second phase, we've already established correctness, so we are ready to shift all of the traffic over to the new
|
||||
version of the application. We'll configure weighted destinations, and shift the traffic while monitoring certain business
|
||||
metrics to ensure the service quality remains at acceptable levels. Once 100% of the traffic is shifted to the new version,
|
||||
the old version can be decommissioned.
|
||||
|
||||
In practice, it may be desirable to only use one of the phases for testing, in which case the other phase can be
|
||||
skipped.
|
||||
|
||||
## Phase 1: Initial canary rollout of v2
|
||||
|
||||
In this phase, we'll deploy `v2`, and then use a header `stage: canary` to start routing a small amount of specific
|
||||
traffic to the new version. We'll use this header to perform some basic smoke testing and make sure `v2` is working the
|
||||
way we'd expect:
|
||||
|
||||
![Subset Routing](/images/blog/2020-04-22-two-phased-canary-rollout-with-gloo/subset-routing.png)
|
||||
|
||||
### Setting up subset routing
|
||||
|
||||
Before deploying our `v2` service, we'll update our virtual service to only route to pods that have the subset label
|
||||
`version: v1`, using a Gloo feature called [subset routing](https://docs.solo.io/gloo/latest/guides/traffic_management/destination_types/subsets/).
|
||||
|
||||
```yaml
|
||||
apiVersion: gateway.solo.io/v1
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
spec:
|
||||
virtualHost:
|
||||
domains:
|
||||
- "*"
|
||||
routes:
|
||||
- matchers:
|
||||
- prefix: /
|
||||
routeAction:
|
||||
single:
|
||||
upstream:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
subset:
|
||||
values:
|
||||
version: v1
|
||||
```
|
||||
|
||||
We can apply them to the cluster with the following commands:
|
||||
|
||||
```
|
||||
kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo-ref-arch/blog-30-mar-20/platform/prog-delivery/two-phased-with-os-gloo/2-initial-subset-routing-to-v2/vs-1.yaml
|
||||
```
|
||||
|
||||
The application should continue to function as before:
|
||||
|
||||
```
|
||||
➜ curl $(glooctl proxy url)/
|
||||
version:v1
|
||||
```
|
||||
|
||||
### Deploying echo v2
|
||||
|
||||
Now we can safely deploy `v2` of the echo application:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: echo-v2
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: echo
|
||||
version: v2
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: echo
|
||||
version: v2
|
||||
spec:
|
||||
containers:
|
||||
- image: hashicorp/http-echo
|
||||
args:
|
||||
- "-text=version:v2"
|
||||
- -listen=:8080
|
||||
imagePullPolicy: Always
|
||||
name: echo-v2
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
```
|
||||
|
||||
We can deploy with the following command:
|
||||
|
||||
```
|
||||
kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo-ref-arch/blog-30-mar-20/platform/prog-delivery/two-phased-with-os-gloo/2-initial-subset-routing-to-v2/echo-v2.yaml
|
||||
```
|
||||
|
||||
Since our gateway is configured to route specifically to the `v1` subset, this should have no effect. However, it does enable
|
||||
`v2` to be routable from the gateway if the `v2` subset is configured for a route.
|
||||
|
||||
Make sure `v2` is running before moving on:
|
||||
|
||||
```bash
|
||||
➜ kubectl get pod -n echo
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
echo-v1-66dbfffb79-2qw86 1/1 Running 0 5m25s
|
||||
echo-v2-86584fbbdb-slp44 1/1 Running 0 93s
|
||||
```
|
||||
|
||||
The application should continue to function as before:
|
||||
|
||||
```
|
||||
➜ curl $(glooctl proxy url)/
|
||||
version:v1
|
||||
```
|
||||
|
||||
### Adding a route to v2 for canary testing
|
||||
|
||||
We'll route to the `v2` subset when the `stage: canary` header is supplied on the request. If the header isn't
|
||||
provided, we'll continue to route to the `v1` subset as before.
|
||||
|
||||
```yaml
|
||||
apiVersion: gateway.solo.io/v1
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
spec:
|
||||
virtualHost:
|
||||
domains:
|
||||
- "*"
|
||||
routes:
|
||||
- matchers:
|
||||
- headers:
|
||||
- name: stage
|
||||
value: canary
|
||||
prefix: /
|
||||
routeAction:
|
||||
single:
|
||||
upstream:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
subset:
|
||||
values:
|
||||
version: v2
|
||||
- matchers:
|
||||
- prefix: /
|
||||
routeAction:
|
||||
single:
|
||||
upstream:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
subset:
|
||||
values:
|
||||
version: v1
|
||||
```
|
||||
|
||||
We can deploy with the following command:
|
||||
|
||||
```
|
||||
kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo-ref-arch/blog-30-mar-20/platform/prog-delivery/two-phased-with-os-gloo/2-initial-subset-routing-to-v2/vs-2.yaml
|
||||
```
|
||||
|
||||
### Canary testing
|
||||
|
||||
Now that we have this route, we can do some testing. First let's ensure that the existing route is working as expected:
|
||||
|
||||
```
|
||||
➜ curl $(glooctl proxy url)/
|
||||
version:v1
|
||||
```
|
||||
|
||||
And now we can start to canary test our new application version:
|
||||
|
||||
```
|
||||
➜ curl $(glooctl proxy url)/ -H "stage: canary"
|
||||
version:v2
|
||||
```
|
||||
|
||||
### Advanced use cases for subset routing
|
||||
|
||||
We may decide that this approach, using user-provided request headers, is too open. Instead, we may
|
||||
want to restrict canary testing to a known, authorized user.
|
||||
|
||||
A common implementation of this that we've seen is for the canary route to require a valid JWT that contains
|
||||
a specific claim to indicate the subject is authorized for canary testing. Enterprise Gloo has out of the box
|
||||
support for verifying JWTs, updating the request headers based on the JWT claims, and recomputing the
|
||||
routing destination based on the updated headers. We'll save that for a future post covering more advanced use
|
||||
cases in canary testing.
|
||||
|
||||
## Phase 2: Shifting all traffic to v2 and decommissioning v1
|
||||
|
||||
At this point, we've deployed `v2`, and created a route for canary testing. If we are satisfied with the
|
||||
results of the testing, we can move on to phase 2 and start shifting the load from `v1` to `v2`. We'll use
|
||||
[weighted destinations](https://docs.solo.io/gloo/latest/guides/traffic_management/destination_types/multi_destination/)
|
||||
in Gloo to manage the load during the migration.
|
||||
|
||||
### Setting up the weighted destinations
|
||||
|
||||
We can change the Gloo route to route to both of these destinations, with weights to decide how much of the traffic should
|
||||
go to the `v1` versus the `v2` subset. To start, we're going to set it up so 100% of the traffic continues to get routed to the
|
||||
`v1` subset, unless the `stage: canary` header was provided as before.
|
||||
|
||||
```yaml
|
||||
apiVersion: gateway.solo.io/v1
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
spec:
|
||||
virtualHost:
|
||||
domains:
|
||||
- "*"
|
||||
routes:
|
||||
# We'll keep our route from before if we want to continue testing with this header
|
||||
- matchers:
|
||||
- headers:
|
||||
- name: stage
|
||||
value: canary
|
||||
prefix: /
|
||||
routeAction:
|
||||
single:
|
||||
upstream:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
subset:
|
||||
values:
|
||||
version: v2
|
||||
# Now we'll route the rest of the traffic to the upstream, load balanced across the two subsets.
|
||||
- matchers:
|
||||
- prefix: /
|
||||
routeAction:
|
||||
multi:
|
||||
destinations:
|
||||
- destination:
|
||||
upstream:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
subset:
|
||||
values:
|
||||
version: v1
|
||||
weight: 100
|
||||
- destination:
|
||||
upstream:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
subset:
|
||||
values:
|
||||
version: v2
|
||||
weight: 0
|
||||
```
|
||||
|
||||
We can apply this virtual service update to the cluster with the following commands:
|
||||
|
||||
```
|
||||
kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo-ref-arch/blog-30-mar-20/platform/prog-delivery/two-phased-with-os-gloo/3-progressive-traffic-shift-to-v2/vs-1.yaml
|
||||
```
|
||||
|
||||
Now the cluster looks like this, for any request that doesn't have the `stage: canary` header:
|
||||
|
||||
![Initialize Traffic Shift](/images/blog/2020-04-22-two-phased-canary-rollout-with-gloo/init-traffic-shift.png)
|
||||
|
||||
With the initial weights, we should see the gateway continue to serve `v1` for all traffic.
|
||||
|
||||
```bash
|
||||
➜ curl $(glooctl proxy url)/
|
||||
version:v1
|
||||
```
|
||||
|
||||
### Commence rollout
|
||||
|
||||
To simulate a load test, let's shift half the traffic to `v2`:
|
||||
|
||||
![Load Test](/images/blog/2020-04-22-two-phased-canary-rollout-with-gloo/load-test.png)
|
||||
|
||||
This can be expressed on our virtual service by adjusting the weights:
|
||||
|
||||
```yaml
|
||||
apiVersion: gateway.solo.io/v1
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
spec:
|
||||
virtualHost:
|
||||
domains:
|
||||
- "*"
|
||||
routes:
|
||||
- matchers:
|
||||
- headers:
|
||||
- name: stage
|
||||
value: canary
|
||||
prefix: /
|
||||
routeAction:
|
||||
single:
|
||||
upstream:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
subset:
|
||||
values:
|
||||
version: v2
|
||||
- matchers:
|
||||
- prefix: /
|
||||
routeAction:
|
||||
multi:
|
||||
destinations:
|
||||
- destination:
|
||||
upstream:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
subset:
|
||||
values:
|
||||
version: v1
|
||||
# Update the weight so 50% of the traffic hits v1
|
||||
weight: 50
|
||||
- destination:
|
||||
upstream:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
subset:
|
||||
values:
|
||||
version: v2
|
||||
# And 50% is routed to v2
|
||||
weight: 50
|
||||
```
|
||||
|
||||
We can apply this to the cluster with the following command:
|
||||
|
||||
```
|
||||
kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo-ref-arch/blog-30-mar-20/platform/prog-delivery/two-phased-with-os-gloo/3-progressive-traffic-shift-to-v2/vs-2.yaml
|
||||
```
|
||||
|
||||
Now when we send traffic to the gateway, we should see half of the requests return `version:v1` and the
|
||||
other half return `version:v2`.
|
||||
|
||||
```
|
||||
➜ curl $(glooctl proxy url)/
|
||||
version:v1
|
||||
➜ curl $(glooctl proxy url)/
|
||||
version:v2
|
||||
➜ curl $(glooctl proxy url)/
|
||||
version:v1
|
||||
```
|
||||
|
||||
In practice, during this process it's likely you'll be monitoring some performance and business metrics
|
||||
to ensure the traffic shift isn't resulting in a decline in the overall quality of service. We can even
|
||||
leverage operators like [Flagger](https://github.com/weaveworks/flagger) to help automate this Gloo
|
||||
workflow. Gloo Enterprise integrates with your metrics backend and provides out of the box and dynamic,
|
||||
upstream-based dashboards that can be used to monitor the health of the rollout.
|
||||
We will save these topics for a future post on advanced canary testing use cases with Gloo.
|
||||
|
||||
### Finishing the rollout
|
||||
|
||||
We will continue adjusting weights until eventually, all of the traffic is now being routed to `v2`:
|
||||
|
||||
![Final Shift](/images/blog/2020-04-22-two-phased-canary-rollout-with-gloo/final-shift.png)
|
||||
|
||||
Our virtual service will look like this:
|
||||
|
||||
```yaml
|
||||
apiVersion: gateway.solo.io/v1
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
spec:
|
||||
virtualHost:
|
||||
domains:
|
||||
- "*"
|
||||
routes:
|
||||
- matchers:
|
||||
- headers:
|
||||
- name: stage
|
||||
value: canary
|
||||
prefix: /
|
||||
routeAction:
|
||||
single:
|
||||
upstream:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
subset:
|
||||
values:
|
||||
version: v2
|
||||
- matchers:
|
||||
- prefix: /
|
||||
routeAction:
|
||||
multi:
|
||||
destinations:
|
||||
- destination:
|
||||
upstream:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
subset:
|
||||
values:
|
||||
version: v1
|
||||
# No traffic will be sent to v1 anymore
|
||||
weight: 0
|
||||
- destination:
|
||||
upstream:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
subset:
|
||||
values:
|
||||
version: v2
|
||||
# Now all the traffic will be routed to v2
|
||||
weight: 100
|
||||
```
|
||||
|
||||
We can apply that to the cluster with the following command:
|
||||
|
||||
```
|
||||
kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo-ref-arch/blog-30-mar-20/platform/prog-delivery/two-phased-with-os-gloo/3-progressive-traffic-shift-to-v2/vs-3.yaml
|
||||
```
|
||||
|
||||
Now when we send traffic to the gateway, we should see all of the requests return `version:v2`.
|
||||
|
||||
```
|
||||
➜ curl $(glooctl proxy url)/
|
||||
version:v2
|
||||
➜ curl $(glooctl proxy url)/
|
||||
version:v2
|
||||
➜ curl $(glooctl proxy url)/
|
||||
version:v2
|
||||
```
|
||||
|
||||
### Decommissioning v1
|
||||
|
||||
At this point, we have deployed the new version of our application, conducted correctness tests using subset routing,
|
||||
conducted load and performance tests by progressively shifting traffic to the new version, and finished
|
||||
the rollout. The only remaining task is to clean up our `v1` resources.
|
||||
|
||||
First, we'll clean up our routes. We'll leave the subset specified on the route so we are all setup for future upgrades.
|
||||
|
||||
```yaml
|
||||
apiVersion: gateway.solo.io/v1
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
spec:
|
||||
virtualHost:
|
||||
domains:
|
||||
- "*"
|
||||
routes:
|
||||
- matchers:
|
||||
- prefix: /
|
||||
routeAction:
|
||||
single:
|
||||
upstream:
|
||||
name: echo
|
||||
namespace: gloo-system
|
||||
subset:
|
||||
values:
|
||||
version: v2
|
||||
```
|
||||
|
||||
We can apply this update with the following command:
|
||||
|
||||
```
|
||||
kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo-ref-arch/blog-30-mar-20/platform/prog-delivery/two-phased-with-os-gloo/4-decommissioning-v1/vs.yaml
|
||||
```
|
||||
|
||||
And we can delete the `v1` deployment, which is no longer serving any traffic.
|
||||
|
||||
```
|
||||
kubectl delete deploy -n echo echo-v1
|
||||
```
|
||||
|
||||
Now our cluster looks like this:
|
||||
|
||||
![End State](/images/blog/2020-04-22-two-phased-canary-rollout-with-gloo/end-state.png)
|
||||
|
||||
And requests to the gateway return this:
|
||||
|
||||
```
|
||||
➜ curl $(glooctl proxy url)/
|
||||
version:v2
|
||||
```
|
||||
|
||||
We have now completed our two-phased canary rollout of an application update using Gloo!
|
||||
|
||||
## Other Advanced Topics
|
||||
|
||||
Over the course of this post, we collected a few topics that could be a good starting point for advanced exploration:
|
||||
|
||||
- Using the **JWT** filter to verify JWTs, extract claims onto headers, and route to canary versions depending on a claim value.
|
||||
- Looking at **Prometheus metrics** and **Grafana dashboards** created by Gloo to monitor the health of the rollout.
|
||||
- Automating the rollout by integrating **Flagger** with **Gloo**.
|
||||
|
||||
A few other topics that warrant further exploration:
|
||||
|
||||
- Supporting **self-service** upgrades by giving teams ownership over their upstream and route configuration
|
||||
- Utilizing Gloo's **delegation** feature and Kubernetes **RBAC** to decentralize the configuration management safely
|
||||
- Fully automating the continuous delivery process by applying **GitOps** principles and using tools like **Flux** to push config to the cluster
|
||||
- Supporting **hybrid** or **non-Kubernetes** application use-cases by setting up Gloo with a different deployment pattern
|
||||
- Utilizing **traffic shadowing** to begin testing the new version with realistic data before shifting production traffic to it
|
||||
|
||||
## Get Involved in the Gloo Community
|
||||
|
||||
Gloo has a large and growing community of open source users, in addition to an enterprise customer base. To learn more about
|
||||
Gloo:
|
||||
|
||||
- Check out the [repo](https://github.com/solo-io/gloo), where you can see the code and file issues
|
||||
- Check out the [docs](https://docs.solo.io/gloo/latest), which have an extensive collection of guides and examples
|
||||
- Join the [slack channel](http://slack.solo.io/) and start chatting with the Solo engineering team and user community
|
||||
|
||||
If you'd like to get in touch with me (feedback is always appreciated!), you can find me on the
|
||||
[Solo slack](http://slack.solo.io/) or email me at **rick.ducott@solo.io**.
|
|
@ -0,0 +1,192 @@
|
|||
---
|
||||
title: "Introducing PodTopologySpread"
|
||||
date: 2020-05-05
|
||||
slug: introducing-podtopologyspread
|
||||
url: /blog/2020/05/Introducing-PodTopologySpread
|
||||
---
|
||||
|
||||
**Author:** Wei Huang (IBM), Aldo Culquicondor (Google)
|
||||
|
||||
Managing Pods distribution across a cluster is hard. The well-known Kubernetes
|
||||
features for Pod affinity and anti-affinity, allow some control of Pod placement
|
||||
in different topologies. However, these features only resolve part of Pods
|
||||
distribution use cases: either place unlimited Pods to a single topology, or
|
||||
disallow two Pods to co-locate in the same topology. In between these two
|
||||
extreme cases, there is a common need to distribute the Pods evenly across the
|
||||
topologies, so as to achieve better cluster utilization and high availability of
|
||||
applications.
|
||||
|
||||
The PodTopologySpread scheduling plugin (originally proposed as EvenPodsSpread)
|
||||
was designed to fill that gap. We promoted it to beta in 1.18.
|
||||
|
||||
## API changes
|
||||
|
||||
A new field `topologySpreadConstraints` is introduced in the Pod's spec API:
|
||||
|
||||
```
|
||||
spec:
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: <integer>
|
||||
topologyKey: <string>
|
||||
whenUnsatisfiable: <string>
|
||||
labelSelector: <object>
|
||||
```
|
||||
|
||||
As this API is embedded in Pod's spec, you can use this feature in all the
|
||||
high-level workload APIs, such as Deployment, DaemonSet, StatefulSet, etc.
|
||||
|
||||
Let's see an example of a cluster to understand this API.
|
||||
|
||||
![API](/images/blog/2020-05-05-introducing-podtopologyspread/api.png)
|
||||
|
||||
- **labelSelector** is used to find matching Pods. For each topology, we count
|
||||
the number of Pods that match this label selector. In the above example, given
|
||||
the labelSelector as "app: foo", the matching number in "zone1" is 2; while
|
||||
the number in "zone2" is 0.
|
||||
- **topologyKey** is the key that defines a topology in the Nodes' labels. In
|
||||
the above example, some Nodes are grouped into "zone1" if they have the label
|
||||
"zone=zone1" label; while other ones are grouped into "zone2".
|
||||
- **maxSkew** describes the maximum degree to which Pods can be unevenly
|
||||
distributed. In the above example:
|
||||
- if we put the incoming Pod to "zone1", the skew on "zone1" will become 3 (3
|
||||
Pods matched in "zone1"; global minimum of 0 Pods matched on "zone2"), which
|
||||
violates the "maxSkew: 1" constraint.
|
||||
- if the incoming Pod is placed to "zone2", the skew on "zone2" is 0 (1 Pod
|
||||
matched in "zone2"; global minimum of 1 Pod matched on "zone2" itself),
|
||||
which satisfies the "maxSkew: 1" constraint. Note that the skew is
|
||||
calculated per each qualified Node, instead of a global skew.
|
||||
- **whenUnsatisfiable** specifies, when "maxSkew" can't be satisfied, what
|
||||
action should be taken:
|
||||
- `DoNotSchedule` (default) tells the scheduler not to schedule it. It's a
|
||||
hard constraint.
|
||||
- `ScheduleAnyway` tells the scheduler to still schedule it while prioritizing
|
||||
Nodes that reduce the skew. It's a soft constraint.
|
||||
|
||||
## Advanced usage
|
||||
|
||||
As the feature name "PodTopologySpread" implies, the basic usage of this feature
|
||||
is to run your workload with an absolute even manner (maxSkew=1), or relatively
|
||||
even manner (maxSkew>=2). See the [official
|
||||
document](/docs/concepts/workloads/pods/pod-topology-spread-constraints/)
|
||||
for more details.
|
||||
|
||||
In addition to this basic usage, there are some advanced usage examples that
|
||||
enable your workloads to benefit on high availability and cluster utilization.
|
||||
|
||||
### Usage along with NodeSelector / NodeAffinity
|
||||
|
||||
You may have found that we didn't have a "topologyValues" field to limit which
|
||||
topologies the Pods are going to be scheduled to. By default, it is going to
|
||||
search all Nodes and group them by "topologyKey". Sometimes this may not be the
|
||||
ideal case. For instance, suppose there is a cluster with Nodes tagged with
|
||||
"env=prod", "env=staging" and "env=qa", and now you want to evenly place Pods to
|
||||
the "qa" environment across zones, is it possible?
|
||||
|
||||
The answer is yes. You can leverage the NodeSelector or NodeAffinity API spec.
|
||||
Under the hood, the PodTopologySpread feature will **honor** that and calculate
|
||||
the spread constraints among the nodes that satisfy the selectors.
|
||||
|
||||
![Advanced-Usage-1](/images/blog/2020-05-05-introducing-podtopologyspread/advanced-usage-1.png)
|
||||
|
||||
As illustrated above, you can specify `spec.affinity.nodeAffinity` to limit the
|
||||
"searching scope" to be "qa" environment, and within that scope, the Pod will be
|
||||
scheduled to one zone which satisfies the topologySpreadConstraints. In this
|
||||
case, it's "zone2".
|
||||
|
||||
### Multiple TopologySpreadConstraints
|
||||
|
||||
It's intuitive to understand how one single TopologySpreadConstraint works.
|
||||
What's the case for multiple TopologySpreadConstraints? Internally, each
|
||||
TopologySpreadConstraint is calculated independently, and the result sets will
|
||||
be merged to generate the eventual result set - i.e., suitable Nodes.
|
||||
|
||||
In the following example, we want to schedule a Pod to a cluster with 2
|
||||
requirements at the same time:
|
||||
|
||||
- place the Pod evenly with Pods across zones
|
||||
- place the Pod evenly with Pods across nodes
|
||||
|
||||
![Advanced-Usage-2](/images/blog/2020-05-05-introducing-podtopologyspread/advanced-usage-2.png)
|
||||
|
||||
For the first constraint, there are 3 Pods in zone1 and 2 Pods in zone2, so the
|
||||
incoming Pod can be only put to zone2 to satisfy the "maxSkew=1" constraint. In
|
||||
other words, the result set is nodeX and nodeY.
|
||||
|
||||
For the second constraint, there are too many Pods in nodeB and nodeX, so the
|
||||
incoming Pod can be only put to nodeA and nodeY.
|
||||
|
||||
Now we can conclude the only qualified Node is nodeY - from the intersection of
|
||||
the sets {nodeX, nodeY} (from the first constraint) and {nodeA, nodeY} (from the
|
||||
second constraint).
|
||||
|
||||
Multiple TopologySpreadConstraints is powerful, but be sure to understand the
|
||||
difference with the preceding "NodeSelector/NodeAffinity" example: one is to
|
||||
calculate result set independently and then interjoined; while the other is to
|
||||
calculate topologySpreadConstraints based on the filtering results of node
|
||||
constraints.
|
||||
|
||||
Instead of using "hard" constraints in all topologySpreadConstraints, you can
|
||||
also combine using "hard" constraints and "soft" constraints to adhere to more
|
||||
diverse cluster situations.
|
||||
|
||||
{{< note >}}
|
||||
If two TopologySpreadConstraints are being applied for the same {topologyKey,
|
||||
whenUnsatisfiable} tuple, the Pod creation will be blocked returning a
|
||||
validation error.
|
||||
{{< /note >}}
|
||||
|
||||
## PodTopologySpread defaults
|
||||
|
||||
PodTopologySpread is a Pod level API. As such, to use the feature, workload
|
||||
authors need to be aware of the underlying topology of the cluster, and then
|
||||
specify proper `topologySpreadConstraints` in the Pod spec for every workload.
|
||||
While the Pod-level API gives the most flexibility it is also possible to
|
||||
specify cluster-level defaults.
|
||||
|
||||
The default PodTopologySpread constraints allow you to specify spreading for all
|
||||
the workloads in the cluster, tailored for its topology. The constraints can be
|
||||
specified by an operator/admin as PodTopologySpread plugin arguments in the
|
||||
[scheduling profile configuration
|
||||
API](/docs/reference/scheduling/profiles/) when starting
|
||||
kube-scheduler.
|
||||
|
||||
A sample configuration could look like this:
|
||||
|
||||
```
|
||||
apiVersion: kubescheduler.config.k8s.io/v1alpha2
|
||||
kind: KubeSchedulerConfiguration
|
||||
profiles:
|
||||
pluginConfig:
|
||||
- name: PodTopologySpread
|
||||
args:
|
||||
defaultConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: example.com/rack
|
||||
whenUnsatisfiable: ScheduleAnyway
|
||||
```
|
||||
|
||||
When configuring default constraints, label selectors must be left empty.
|
||||
kube-scheduler will deduce the label selectors from the membership of the Pod to
|
||||
Services, ReplicationControllers, ReplicaSets or StatefulSets. Pods can
|
||||
always override the default constraints by providing their own through the
|
||||
PodSpec.
|
||||
|
||||
{{< note >}}
|
||||
When using default PodTopologySpread constraints, it is recommended to disable
|
||||
the old DefaultTopologySpread plugin.
|
||||
{{< /note >}}
|
||||
|
||||
## Wrap-up
|
||||
|
||||
PodTopologySpread allows you to define spreading constraints for your workloads
|
||||
with a flexible and expressive Pod-level API. In the past, workload authors used
|
||||
Pod AntiAffinity rules to force or hint the scheduler to run a single Pod per
|
||||
topology domain. In contrast, the new PodTopologySpread constraints allow Pods
|
||||
to specify skew levels that can be required (hard) or desired (soft). The
|
||||
feature can be paired with Node selectors and Node affinity to limit the
|
||||
spreading to specific domains. Pod spreading constraints can be defined for
|
||||
different topologies such as hostnames, zones, regions, racks, etc.
|
||||
|
||||
Lastly, cluster operators can define default constraints to be applied to all
|
||||
Pods. This way, Pods don't need to be aware of the underlying topology of the
|
||||
cluster.
|
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
title: "How Docs Handle Third Party and Dual Sourced Content"
|
||||
date: 2020-05-06
|
||||
slug: third-party-dual-sourced
|
||||
url: /blog/2020/05/third-party-dual-sourced-content
|
||||
---
|
||||
|
||||
**Author:** Zach Corleissen, Cloud Native Computing Foundation
|
||||
|
||||
*Editor's note: Zach is one of the chairs for the Kubernetes documentation special interest group (SIG Docs).*
|
||||
|
||||
Late last summer, SIG Docs started a community conversation about third party content in Kubernetes docs. This conversation became a [Kubernetes Enhancement Proposal](https://github.com/kubernetes/enhancements/pull/1327) (KEP) and, after five months for review and comment, SIG Architecture approved the KEP as a [content guide](/docs/contribute/style/content-guide/) for Kubernetes docs.
|
||||
|
||||
Here's how Kubernetes docs handle third party content now:
|
||||
|
||||
> Links to active content in the Kubernetes project (projects in the kubernetes and kubernetes-sigs GitHub orgs) are always allowed.
|
||||
>
|
||||
> Kubernetes requires some third party content to function. Examples include container runtimes (containerd, CRI-O, Docker), networking policy (CNI plugins), Ingress controllers, and logging.
|
||||
>
|
||||
> Docs can link to third party open source software (OSS) outside the Kubernetes project if it’s necessary for Kubernetes to function.
|
||||
|
||||
These common sense guidelines make sure that Kubernetes docs document Kubernetes.
|
||||
|
||||
## Keeping the docs focused
|
||||
|
||||
Our goal is for Kubernetes docs to be a trustworthy guide to Kubernetes features. To achieve this goal, SIG Docs is [tracking third party content](https://github.com/kubernetes/website/issues/20232) and removing any third party content that isn't both in the Kubernetes project _and_ required for Kubernetes to function.
|
||||
|
||||
### Re-homing content
|
||||
|
||||
Some content will be removed that readers may find helpful. To make sure readers have continous access to information, we're giving stakeholders until the [1.19 release deadline for docs](https://github.com/kubernetes/sig-release/tree/master/releases/release-1.19), **July 9th, 2020** to re-home any content slated for removal.
|
||||
|
||||
Over the next few months you'll see less third party content in the docs as contributors open PRs to remove content.
|
||||
|
||||
## Background
|
||||
|
||||
Over time, SIG Docs observed increasing vendor content in the docs. Some content took the form of vendor-specific implementations that aren't required for Kubernetes to function in-project. Other content was thinly-disguised advertising with minimal to no feature content. Some vendor content was new; other content had been in the docs for years. It became clear that the docs needed clear, well-bounded guidelines for what kind of third party content is and isn't allowed. The [content guide](https://kubernetes.io/docs/contribute/content-guide/) emerged from an extensive period for review and comment from the community.
|
||||
|
||||
Docs work best when they're accurate, helpful, trustworthy, and remain focused on features. In our experience, vendor content dilutes trust and accuracy.
|
||||
|
||||
Put simply: feature docs aren't a place for vendors to advertise their products. Our content policy keeps the docs focused on helping developers and cluster admins, not on marketing.
|
||||
|
||||
## Dual sourced content
|
||||
|
||||
Less impactful but also important is how Kubernetes docs handle _dual-sourced content_. Dual-sourced content is content published in more than one location, or from a non-canonical source.
|
||||
|
||||
From the [Kubernetes content guide](https://kubernetes.io/docs/contribute/style/content-guide/#dual-sourced-content):
|
||||
|
||||
> Wherever possible, Kubernetes docs link to canonical sources instead of hosting dual-sourced content.
|
||||
|
||||
Minimizing dual-sourced content streamlines the docs and makes content across the Web more searchable. We're working to consolidate and redirect dual-sourced content in the Kubernetes docs as well.
|
||||
|
||||
## Ways to contribute
|
||||
|
||||
We're tracking third-party content in an [issue in the Kubernetes website repository](https://github.com/kubernetes/website/issues/20232). If you see third party content that's out of project and isn't required for Kubernetes to function, please comment on the tracking issue.
|
||||
|
||||
Feel free to open a PR that removes non-conforming content once you've identified it!
|
||||
|
||||
## Want to know more?
|
||||
|
||||
For more information, read the issue description for [tracking third party content](https://github.com/kubernetes/website/issues/20232).
|
|
@ -0,0 +1,589 @@
|
|||
---
|
||||
layout: blog
|
||||
title: "WSL+Docker: Kubernetes on the Windows Desktop"
|
||||
date: 2020-05-21
|
||||
slug: wsl-docker-kubernetes-on-the-windows-desktop
|
||||
---
|
||||
|
||||
**Authors**: [Nuno do Carmo](https://twitter.com/nunixtech) Docker Captain and WSL Corsair; [Ihor Dvoretskyi](https://twitter.com/idvoretskyi), Developer Advocate, Cloud Native Computing Foundation
|
||||
|
||||
# Introduction
|
||||
|
||||
New to Windows 10 and WSL2, or new to Docker and Kubernetes? Welcome to this blog post where we will install from scratch Kubernetes in Docker [KinD](https://kind.sigs.k8s.io/) and [Minikube](https://minikube.sigs.k8s.io/docs/).
|
||||
|
||||
|
||||
# Why Kubernetes on Windows?
|
||||
|
||||
For the last few years, Kubernetes became a de-facto standard platform for running containerized services and applications in distributed environments. While a wide variety of distributions and installers exist to deploy Kubernetes in the cloud environments (public, private or hybrid), or within the bare metal environments, there is still a need to deploy and run Kubernetes locally, for example, on the developer's workstation.
|
||||
|
||||
Kubernetes has been originally designed to be deployed and used in the Linux environments. However, a good number of users (and not only application developers) use Windows OS as their daily driver. When Microsoft revealed WSL - [the Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/), the line between Windows and Linux environments became even less visible.
|
||||
|
||||
|
||||
Also, WSL brought an ability to run Kubernetes on Windows almost seamlessly!
|
||||
|
||||
|
||||
Below, we will cover in brief how to install and use various solutions to run Kubernetes locally.
|
||||
|
||||
# Prerequisites
|
||||
|
||||
Since we will explain how to install KinD, we won't go into too much detail around the installation of KinD's dependencies.
|
||||
|
||||
However, here is the list of the prerequisites needed and their version/lane:
|
||||
|
||||
- OS: Windows 10 version 2004, Build 19041
|
||||
- [WSL2 enabled](https://docs.microsoft.com/en-us/windows/wsl/wsl2-install)
|
||||
- In order to install the distros as WSL2 by default, once WSL2 installed, run the command `wsl.exe --set-default-version 2` in Powershell
|
||||
- WSL2 distro installed from the Windows Store - the distro used is Ubuntu-18.04
|
||||
- [Docker Desktop for Windows](https://hub.docker.com/editions/community/docker-ce-desktop-windows), stable channel - the version used is 2.2.0.4
|
||||
- [Optional] Microsoft Terminal installed from the Windows Store
|
||||
- Open the Windows store and type "Terminal" in the search, it will be (normally) the first option
|
||||
|
||||
![Windows Store Terminal](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-windows-store-terminal.png)
|
||||
|
||||
And that's actually it. For Docker Desktop for Windows, no need to configure anything yet as we will explain it in the next section.
|
||||
|
||||
# WSL2: First contact
|
||||
|
||||
Once everything is installed, we can launch the WSL2 terminal from the Start menu, and type "Ubuntu" for searching the applications and documents:
|
||||
|
||||
![Start Menu Search](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-start-menu-search.png)
|
||||
|
||||
Once found, click on the name and it will launch the default Windows console with the Ubuntu bash shell running.
|
||||
|
||||
Like for any normal Linux distro, you need to create a user and set a password:
|
||||
|
||||
![User-Password](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-user-password.png)
|
||||
|
||||
## [Optional] Update the `sudoers`
|
||||
|
||||
As we are working, normally, on our local computer, it might be nice to update the `sudoers` and set the group `%sudo` to be password-less:
|
||||
|
||||
```bash
|
||||
# Edit the sudoers with the visudo command
|
||||
sudo visudo
|
||||
|
||||
# Change the %sudo group to be password-less
|
||||
%sudo ALL=(ALL:ALL) NOPASSWD: ALL
|
||||
|
||||
# Press CTRL+X to exit
|
||||
# Press Y to save
|
||||
# Press Enter to confirm
|
||||
```
|
||||
|
||||
![visudo](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-visudo.png)
|
||||
|
||||
## Update Ubuntu
|
||||
|
||||
Before we move to the Docker Desktop settings, let's update our system and ensure we start in the best conditions:
|
||||
|
||||
```bash
|
||||
# Update the repositories and list of the packages available
|
||||
sudo apt update
|
||||
# Update the system based on the packages installed > the "-y" will approve the change automatically
|
||||
sudo apt upgrade -y
|
||||
```
|
||||
|
||||
![apt-update-upgrade](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-apt-update-upgrade.png)
|
||||
|
||||
# Docker Desktop: faster with WSL2
|
||||
|
||||
Before we move into the settings, let's do a small test, it will display really how cool the new integration with Docker Desktop is:
|
||||
|
||||
```bash
|
||||
# Try to see if the docker cli and daemon are installed
|
||||
docker version
|
||||
# Same for kubectl
|
||||
kubectl version
|
||||
```
|
||||
|
||||
![kubectl-error](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-docker-kubectl-error.png)
|
||||
|
||||
You got an error? Perfect! It's actually good news, so let's now move on to the settings.
|
||||
|
||||
## Docker Desktop settings: enable WSL2 integration
|
||||
|
||||
First let's start Docker Desktop for Windows if it's not still the case. Open the Windows start menu and type "docker", click on the name to start the application:
|
||||
|
||||
![docker-start](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-docker-start.png)
|
||||
|
||||
You should now see the Docker icon with the other taskbar icons near the clock:
|
||||
|
||||
![docker-taskbar](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-docker-taskbar.png)
|
||||
|
||||
Now click on the Docker icon and choose settings. A new window will appear:
|
||||
|
||||
![docker-settings-general](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-docker-settings-general.png)
|
||||
|
||||
By default, the WSL2 integration is not active, so click the "Enable the experimental WSL 2 based engine" and click "Apply & Restart":
|
||||
|
||||
![docker-settings-wsl2](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-docker-settings-wsl2-activated.png)
|
||||
|
||||
What this feature did behind the scenes was to create two new distros in WSL2, containing and running all the needed backend sockets, daemons and also the CLI tools (read: docker and kubectl command).
|
||||
|
||||
Still, this first setting is still not enough to run the commands inside our distro. If we try, we will have the same error as before.
|
||||
|
||||
In order to fix it, and finally be able to use the commands, we need to tell the Docker Desktop to "attach" itself to our distro also:
|
||||
|
||||
![docker-resources-wsl](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-docker-resources-wsl-integration.png)
|
||||
|
||||
Let's now switch back to our WSL2 terminal and see if we can (finally) launch the commands:
|
||||
|
||||
```bash
|
||||
# Try to see if the docker cli and daemon are installed
|
||||
docker version
|
||||
# Same for kubectl
|
||||
kubectl version
|
||||
```
|
||||
|
||||
![docker-kubectl-success](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-docker-kubectl-success.png)
|
||||
|
||||
> Tip: if nothing happens, restart Docker Desktop and restart the WSL process in Powershell: `Restart-Service LxssManager` and launch a new Ubuntu session
|
||||
|
||||
And success! The basic settings are now done and we move to the installation of KinD.
|
||||
|
||||
# KinD: Kubernetes made easy in a container
|
||||
|
||||
Right now, we have Docker that is installed, configured and the last test worked fine.
|
||||
|
||||
However, if we look carefully at the `kubectl` command, it found the "Client Version" (1.15.5), but it didn't find any server.
|
||||
|
||||
This is normal as we didn't enable the Docker Kubernetes cluster. So let's install KinD and create our first cluster.
|
||||
|
||||
And as sources are always important to mention, we will follow (partially) the how-to on the [official KinD website](https://kind.sigs.k8s.io/docs/user/quick-start/):
|
||||
|
||||
```bash
|
||||
# Download the latest version of KinD
|
||||
curl -Lo ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.7.0/kind-$(uname)-amd64
|
||||
# Make the binary executable
|
||||
chmod +x ./kind
|
||||
# Move the binary to your executable path
|
||||
sudo mv ./kind /usr/local/bin/
|
||||
```
|
||||
|
||||
![kind-install](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-kind-install.png)
|
||||
|
||||
## KinD: the first cluster
|
||||
|
||||
We are ready to create our first cluster:
|
||||
|
||||
```bash
|
||||
# Check if the KUBECONFIG is not set
|
||||
echo $KUBECONFIG
|
||||
# Check if the .kube directory is created > if not, no need to create it
|
||||
ls $HOME/.kube
|
||||
# Create the cluster and give it a name (optional)
|
||||
kind create cluster --name wslkind
|
||||
# Check if the .kube has been created and populated with files
|
||||
ls $HOME/.kube
|
||||
```
|
||||
|
||||
![kind-cluster-create](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-kind-cluster-create.png)
|
||||
|
||||
> Tip: as you can see, the Terminal was changed so the nice icons are all displayed
|
||||
|
||||
The cluster has been successfully created, and because we are using Docker Desktop, the network is all set for us to use "as is".
|
||||
|
||||
So we can open the `Kubernetes master` URL in our Windows browser:
|
||||
|
||||
![kind-browser-k8s-master](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-kind-browse-k8s-master.png)
|
||||
|
||||
And this is the real strength from Docker Desktop for Windows with the WSL2 backend. Docker really did an amazing integration.
|
||||
|
||||
## KinD: counting 1 - 2 - 3
|
||||
|
||||
Our first cluster was created and it's the "normal" one node cluster:
|
||||
|
||||
```bash
|
||||
# Check how many nodes it created
|
||||
kubectl get nodes
|
||||
# Check the services for the whole cluster
|
||||
kubectl get all --all-namespaces
|
||||
```
|
||||
|
||||
![kind-list-nodes-services](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-kind-list-nodes-services.png)
|
||||
|
||||
While this will be enough for most people, let's leverage one of the coolest feature, multi-node clustering:
|
||||
|
||||
|
||||
```bash
|
||||
# Delete the existing cluster
|
||||
kind delete cluster --name wslkind
|
||||
# Create a config file for a 3 nodes cluster
|
||||
cat << EOF > kind-3nodes.yaml
|
||||
kind: Cluster
|
||||
apiVersion: kind.x-k8s.io/v1alpha4
|
||||
nodes:
|
||||
- role: control-plane
|
||||
- role: worker
|
||||
- role: worker
|
||||
EOF
|
||||
# Create a new cluster with the config file
|
||||
kind create cluster --name wslkindmultinodes --config ./kind-3nodes.yaml
|
||||
# Check how many nodes it created
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
![kind-cluster-create-multinodes](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-kind-cluster-create-multinodes.png)
|
||||
|
||||
> Tip: depending on how fast we run the "get nodes" command, it can be that not all the nodes are ready, wait few seconds and run it again, everything should be ready
|
||||
|
||||
And that's it, we have created a three-node cluster, and if we look at the services one more time, we will see several that have now three replicas:
|
||||
|
||||
|
||||
```bash
|
||||
# Check the services for the whole cluster
|
||||
kubectl get all --all-namespaces
|
||||
```
|
||||
|
||||
![wsl2-kind-list-services-multinodes](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-kind-list-services-multinodes.png)
|
||||
|
||||
## KinD: can I see a nice dashboard?
|
||||
|
||||
Working on the command line is always good and very insightful. However, when dealing with Kubernetes we might want, at some point, to have a visual overview.
|
||||
|
||||
For that, the [Kubernetes Dashboard](https://github.com/kubernetes/dashboard) project has been created. The installation and first connection test is quite fast, so let's do it:
|
||||
|
||||
```bash
|
||||
# Install the Dashboard application into our cluster
|
||||
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc6/aio/deploy/recommended.yaml
|
||||
# Check the resources it created based on the new namespace created
|
||||
kubectl get all -n kubernetes-dashboard
|
||||
```
|
||||
|
||||
![kind-install-dashboard](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-kind-install-dashboard.png)
|
||||
|
||||
As it created a service with a ClusterIP (read: internal network address), we cannot reach it if we type the URL in our Windows browser:
|
||||
|
||||
![kind-browse-dashboard-error](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-kind-browse-dashboard-error.png)
|
||||
|
||||
That's because we need to create a temporary proxy:
|
||||
|
||||
|
||||
```bash
|
||||
# Start a kubectl proxy
|
||||
kubectl proxy
|
||||
# Enter the URL on your browser: http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
|
||||
```
|
||||
|
||||
![kind-browse-dashboard-success](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-kind-browse-dashboard-success.png)
|
||||
|
||||
Finally to login, we can either enter a Token, which we didn't create, or enter the `kubeconfig` file from our Cluster.
|
||||
|
||||
If we try to login with the `kubeconfig`, we will get the error "Internal error (500): Not enough data to create auth info structure". This is due to the lack of credentials in the `kubeconfig` file.
|
||||
|
||||
So to avoid you ending with the same error, let's follow the [recommended RBAC approach](https://github.com/kubernetes/dashboard/blob/master/docs/user/access-control/creating-sample-user.md).
|
||||
|
||||
Let's open a new WSL2 session:
|
||||
|
||||
```bash
|
||||
# Create a new ServiceAccount
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: admin-user
|
||||
namespace: kubernetes-dashboard
|
||||
EOF
|
||||
# Create a ClusterRoleBinding for the ServiceAccount
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: admin-user
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: cluster-admin
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: admin-user
|
||||
namespace: kubernetes-dashboard
|
||||
EOF
|
||||
```
|
||||
|
||||
![kind-browse-dashboard-rbac-serviceaccount](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-kind-browse-dashboard-rbac-serviceaccount.png)
|
||||
|
||||
```bash
|
||||
# Get the Token for the ServiceAccount
|
||||
kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')
|
||||
# Copy the token and copy it into the Dashboard login and press "Sign in"
|
||||
```
|
||||
|
||||
![kind-browse-dashboard-login-success](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-kind-browse-dashboard-login-success.png)
|
||||
|
||||
Success! And let's see our nodes listed also:
|
||||
|
||||
![kind-browse-dashboard-browse-nodes](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-kind-browse-dashboard-browse-nodes.png)
|
||||
|
||||
A nice and shiny three nodes appear.
|
||||
|
||||
# Minikube: Kubernetes from everywhere
|
||||
|
||||
Right now, we have Docker that is installed, configured and the last test worked fine.
|
||||
|
||||
However, if we look carefully at the `kubectl` command, it found the "Client Version" (1.15.5), but it didn't find any server.
|
||||
|
||||
This is normal as we didn't enable the Docker Kubernetes cluster. So let's install Minikube and create our first cluster.
|
||||
|
||||
And as sources are always important to mention, we will follow (partially) the how-to from the [Kubernetes.io website](https://kubernetes.io/docs/tasks/tools/install-minikube/):
|
||||
|
||||
```bash
|
||||
# Download the latest version of Minikube
|
||||
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
|
||||
# Make the binary executable
|
||||
chmod +x ./minikube
|
||||
# Move the binary to your executable path
|
||||
sudo mv ./minikube /usr/local/bin/
|
||||
```
|
||||
|
||||
![minikube-install](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-minikube-install.png)
|
||||
|
||||
## Minikube: updating the host
|
||||
|
||||
If we follow the how-to, it states that we should use the `--driver=none` flag in order to run Minikube directly on the host and Docker.
|
||||
|
||||
Unfortunately, we will get an error about "conntrack" being required to run Kubernetes v 1.18:
|
||||
|
||||
```bash
|
||||
# Create a minikube one node cluster
|
||||
minikube start --driver=none
|
||||
```
|
||||
|
||||
![minikube-start-error](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-minikube-start-error.png)
|
||||
|
||||
> Tip: as you can see, the Terminal was changed so the nice icons are all displayed
|
||||
|
||||
So let's fix the issue by installing the missing package:
|
||||
|
||||
```bash
|
||||
# Install the conntrack package
|
||||
sudo apt install -y conntrack
|
||||
```
|
||||
|
||||
![minikube-install-conntrack](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-minikube-install conntrack.png)
|
||||
|
||||
Let's try to launch it again:
|
||||
|
||||
```bash
|
||||
# Create a minikube one node cluster
|
||||
minikube start --driver=none
|
||||
# We got a permissions error > try again with sudo
|
||||
sudo minikube start --driver=none
|
||||
```
|
||||
|
||||
![minikube-start-error-systemd](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-minikube-start-error-systemd.png)
|
||||
|
||||
Ok, this error cloud be problematic ... in the past. Luckily for us, there's a solution
|
||||
|
||||
## Minikube: enabling SystemD
|
||||
|
||||
In order to enable SystemD on WSL2, we will apply the [scripts](https://forum.snapcraft.io/t/running-snaps-on-wsl2-insiders-only-for-now/13033) from [Daniel Llewellyn](https://twitter.com/diddledan).
|
||||
|
||||
I invite you to read the full blog post and how he came to the solution, and the various iterations he did to fix several issues.
|
||||
|
||||
So in a nutshell, here are the commands:
|
||||
|
||||
```bash
|
||||
# Install the needed packages
|
||||
sudo apt install -yqq daemonize dbus-user-session fontconfig
|
||||
```
|
||||
|
||||
![minikube-systemd-packages](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-minikube-systemd-packages.png)
|
||||
|
||||
```bash
|
||||
# Create the start-systemd-namespace script
|
||||
sudo vi /usr/sbin/start-systemd-namespace
|
||||
#!/bin/bash
|
||||
|
||||
SYSTEMD_PID=$(ps -ef | grep '/lib/systemd/systemd --system-unit=basic.target$' | grep -v unshare | awk '{print $2}')
|
||||
if [ -z "$SYSTEMD_PID" ] || [ "$SYSTEMD_PID" != "1" ]; then
|
||||
export PRE_NAMESPACE_PATH="$PATH"
|
||||
(set -o posix; set) | \
|
||||
grep -v "^BASH" | \
|
||||
grep -v "^DIRSTACK=" | \
|
||||
grep -v "^EUID=" | \
|
||||
grep -v "^GROUPS=" | \
|
||||
grep -v "^HOME=" | \
|
||||
grep -v "^HOSTNAME=" | \
|
||||
grep -v "^HOSTTYPE=" | \
|
||||
grep -v "^IFS='.*"$'\n'"'" | \
|
||||
grep -v "^LANG=" | \
|
||||
grep -v "^LOGNAME=" | \
|
||||
grep -v "^MACHTYPE=" | \
|
||||
grep -v "^NAME=" | \
|
||||
grep -v "^OPTERR=" | \
|
||||
grep -v "^OPTIND=" | \
|
||||
grep -v "^OSTYPE=" | \
|
||||
grep -v "^PIPESTATUS=" | \
|
||||
grep -v "^POSIXLY_CORRECT=" | \
|
||||
grep -v "^PPID=" | \
|
||||
grep -v "^PS1=" | \
|
||||
grep -v "^PS4=" | \
|
||||
grep -v "^SHELL=" | \
|
||||
grep -v "^SHELLOPTS=" | \
|
||||
grep -v "^SHLVL=" | \
|
||||
grep -v "^SYSTEMD_PID=" | \
|
||||
grep -v "^UID=" | \
|
||||
grep -v "^USER=" | \
|
||||
grep -v "^_=" | \
|
||||
cat - > "$HOME/.systemd-env"
|
||||
echo "PATH='$PATH'" >> "$HOME/.systemd-env"
|
||||
exec sudo /usr/sbin/enter-systemd-namespace "$BASH_EXECUTION_STRING"
|
||||
fi
|
||||
if [ -n "$PRE_NAMESPACE_PATH" ]; then
|
||||
export PATH="$PRE_NAMESPACE_PATH"
|
||||
fi
|
||||
```
|
||||
|
||||
```bash
|
||||
# Create the enter-systemd-namespace
|
||||
sudo vi /usr/sbin/enter-systemd-namespace
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$UID" != 0 ]; then
|
||||
echo "You need to run $0 through sudo"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SYSTEMD_PID="$(ps -ef | grep '/lib/systemd/systemd --system-unit=basic.target$' | grep -v unshare | awk '{print $2}')"
|
||||
if [ -z "$SYSTEMD_PID" ]; then
|
||||
/usr/sbin/daemonize /usr/bin/unshare --fork --pid --mount-proc /lib/systemd/systemd --system-unit=basic.target
|
||||
while [ -z "$SYSTEMD_PID" ]; do
|
||||
SYSTEMD_PID="$(ps -ef | grep '/lib/systemd/systemd --system-unit=basic.target$' | grep -v unshare | awk '{print $2}')"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -n "$SYSTEMD_PID" ] && [ "$SYSTEMD_PID" != "1" ]; then
|
||||
if [ -n "$1" ] && [ "$1" != "bash --login" ] && [ "$1" != "/bin/bash --login" ]; then
|
||||
exec /usr/bin/nsenter -t "$SYSTEMD_PID" -a \
|
||||
/usr/bin/sudo -H -u "$SUDO_USER" \
|
||||
/bin/bash -c 'set -a; source "$HOME/.systemd-env"; set +a; exec bash -c '"$(printf "%q" "$@")"
|
||||
else
|
||||
exec /usr/bin/nsenter -t "$SYSTEMD_PID" -a \
|
||||
/bin/login -p -f "$SUDO_USER" \
|
||||
$(/bin/cat "$HOME/.systemd-env" | grep -v "^PATH=")
|
||||
fi
|
||||
echo "Existential crisis"
|
||||
fi
|
||||
```
|
||||
|
||||
```bash
|
||||
# Edit the permissions of the enter-systemd-namespace script
|
||||
sudo chmod +x /usr/sbin/enter-systemd-namespace
|
||||
# Edit the bash.bashrc file
|
||||
sudo sed -i 2a"# Start or enter a PID namespace in WSL2\nsource /usr/sbin/start-systemd-namespace\n" /etc/bash.bashrc
|
||||
```
|
||||
|
||||
![minikube-systemd-files](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-minikube-systemd-files.png)
|
||||
|
||||
Finally, exit and launch a new session. You **do not** need to stop WSL2, a new session is enough:
|
||||
|
||||
![minikube-systemd-enabled](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-minikube-systemd-enabled.png)
|
||||
|
||||
## Minikube: the first cluster
|
||||
|
||||
We are ready to create our first cluster:
|
||||
|
||||
```bash
|
||||
# Check if the KUBECONFIG is not set
|
||||
echo $KUBECONFIG
|
||||
# Check if the .kube directory is created > if not, no need to create it
|
||||
ls $HOME/.kube
|
||||
# Check if the .minikube directory is created > if yes, delete it
|
||||
ls $HOME/.minikube
|
||||
# Create the cluster with sudo
|
||||
sudo minikube start --driver=none
|
||||
```
|
||||
|
||||
In order to be able to use `kubectl` with our user, and not `sudo`, Minikube recommends running the `chown` command:
|
||||
|
||||
```bash
|
||||
# Change the owner of the .kube and .minikube directories
|
||||
sudo chown -R $USER $HOME/.kube $HOME/.minikube
|
||||
# Check the access and if the cluster is running
|
||||
kubectl cluster-info
|
||||
# Check the resources created
|
||||
kubectl get all --all-namespaces
|
||||
```
|
||||
|
||||
![minikube-start-fixed](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-minikube-start-fixed.png)
|
||||
|
||||
The cluster has been successfully created, and Minikube used the WSL2 IP, which is great for several reasons, and one of them is that we can open the `Kubernetes master` URL in our Windows browser:
|
||||
|
||||
![minikube-browse-k8s-master](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-minikube-browse-k8s-master.png)
|
||||
|
||||
And the real strength of WSL2 integration, the port `8443` once open on WSL2 distro, it actually forwards it to Windows, so instead of the need to remind the IP address, we can also reach the `Kubernetes master` URL via `localhost`:
|
||||
|
||||
![minikube-browse-k8s-master-localhost](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-minikube-browse-k8s-master-localhost.png)
|
||||
|
||||
## Minikube: can I see a nice dashboard?
|
||||
|
||||
Working on the command line is always good and very insightful. However, when dealing with Kubernetes we might want, at some point, to have a visual overview.
|
||||
|
||||
For that, Minikube embeded the [Kubernetes Dashboard](https://github.com/kubernetes/dashboard). Thanks to it, running and accessing the Dashboard is very simple:
|
||||
|
||||
```bash
|
||||
# Enable the Dashboard service
|
||||
sudo minikube dashboard
|
||||
# Access the Dashboard from a browser on Windows side
|
||||
```
|
||||
|
||||
![minikube-browse-dashboard](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-minikube-browse-dashboard.png)
|
||||
|
||||
The command creates also a proxy, which means that once we end the command, by pressing `CTRL+C`, the Dashboard will no more be accessible.
|
||||
|
||||
Still, if we look at the namespace `kubernetes-dashboard`, we will see that the service is still created:
|
||||
|
||||
```bash
|
||||
# Get all the services from the dashboard namespace
|
||||
kubectl get all --namespace kubernetes-dashboard
|
||||
```
|
||||
|
||||
![minikube-dashboard-get-all](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-minikube-dashboard-get-all.png)
|
||||
|
||||
Let's edit the service and change it's type to `LoadBalancer`:
|
||||
|
||||
```bash
|
||||
# Edit the Dashoard service
|
||||
kubectl edit service/kubernetes-dashboard --namespace kubernetes-dashboard
|
||||
# Go to the very end and remove the last 2 lines
|
||||
status:
|
||||
loadBalancer: {}
|
||||
# Change the type from ClusterIO to LoadBalancer
|
||||
type: LoadBalancer
|
||||
# Save the file
|
||||
```
|
||||
|
||||
![minikube-dashboard-type-loadbalancer](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-minikube-dashboard-type-loadbalancer.png)
|
||||
|
||||
Check again the Dashboard service and let's access the Dashboard via the LoadBalancer:
|
||||
|
||||
```bash
|
||||
# Get all the services from the dashboard namespace
|
||||
kubectl get all --namespace kubernetes-dashboard
|
||||
# Access the Dashboard from a browser on Windows side with the URL: localhost:<port exposed>
|
||||
```
|
||||
|
||||
![minikube-browse-dashboard-loadbalancer](/images/blog/2020-05-21-wsl2-dockerdesktop-k8s/wsl2-minikube-browse-dashboard-loadbalancer.png)
|
||||
|
||||
# Conclusion
|
||||
|
||||
It's clear that we are far from done as we could have some LoadBalancing implemented and/or other services (storage, ingress, registry, etc...).
|
||||
|
||||
Concerning Minikube on WSL2, as it needed to enable SystemD, we can consider it as an intermediate level to be implemented.
|
||||
|
||||
So with two solutions, what could be the "best for you"? Both bring their own advantages and inconveniences, so here an overview from our point of view solely:
|
||||
|
||||
| Criteria | KinD | Minikube |
|
||||
| -------------------- | ----------------------------- | -------- |
|
||||
| Installation on WSL2 | Very Easy | Medium |
|
||||
| Multi-node | Yes | No |
|
||||
| Plugins | Manual install | Yes |
|
||||
| Persistence | Yes, however not designed for | Yes |
|
||||
| Alternatives | K3d | Microk8s |
|
||||
|
||||
We hope you could have a real taste of the integration between the different components: WSL2 - Docker Desktop - KinD/Minikube. And that gave you some ideas or, even better, some answers to your Kubernetes workflows with KinD and/or Minikube on Windows and WSL2.
|
||||
|
||||
See you soon for other adventures in the Kubernetes ocean.
|
||||
|
||||
[Nuno](https://twitter.com/nunixtech) & [Ihor](https://twitter.com/idvoretskyi)
|
|
@ -0,0 +1,67 @@
|
|||
---
|
||||
layout: blog
|
||||
title: "An Introduction to the K8s-Infrastructure Working Group"
|
||||
date: 2020-05-27
|
||||
slug: an-introduction-to-the-k8s-infrastructure-working-group
|
||||
---
|
||||
|
||||
**Author**: [Kiran "Rin" Oliver](https://twitter.com/kiran_oliver) Storyteller, Kubernetes Upstream Marketing Team
|
||||
|
||||
# An Introduction to the K8s-Infrastructure Working Group
|
||||
|
||||
*Welcome to part one of a new series introducing the K8s-Infrastructure working group!*
|
||||
|
||||
When Kubernetes was formed in 2014, Google undertook the task of building and maintaining the infrastructure necessary for keeping the project running smoothly. The tools itself were open source, but the Google Cloud Platform project used to run the infrastructure was internal-only, preventing contributors from being able to help out. In August 2018, Google granted the Cloud Native Computing Foundation [$9M in credits for the operation of Kubernetes](https://cloud.google.com/blog/products/gcp/google-cloud-grants-9m-in-credits-for-the-operation-of-the-kubernetes-project). The sentiment behind this was that a project such as Kubernetes should be both maintained and operated by the community itself rather than by a single vendor.
|
||||
|
||||
A group of community members enthusiastically undertook the task of collaborating on the path forward, realizing that there was a [more formal infrastructure necessary](https://github.com/kubernetes/community/issues/2715). They joined together as a cross-team working group with ownership spanning across multiple Kubernetes SIGs (Architecture, Contributor Experience, Release, and Testing). [Aaron Crickenberger](https://twitter.com/spiffxp) worked with the Kubernetes Steering Committee to enable the formation of the working group, co-drafting a charter alongside long-time collaborator [Davanum Srinivas](https://twitter.com/dims), and by 2019 the working group was official.
|
||||
|
||||
## What Issues Does the K8s-Infrastructure Working Group Tackle?
|
||||
|
||||
The team took on the complex task of managing the many moving parts of the infrastructure that sustains Kubernetes as a project.
|
||||
|
||||
The need started with necessity: the first problem they took on was a complete migration of all of the project's infrastructure from Google-owned infrastructure to the Cloud Native Computing Foundation (CNCF). This is being done so that the project is self-sustainable without the need of any direct assistance from individual vendors. This breaks down in the following ways:
|
||||
|
||||
* Identifying what infrastructure the Kubernetes project depends on.
|
||||
* What applications are running?
|
||||
* Where does it run?
|
||||
* Where is its source code?
|
||||
* What is custom built?
|
||||
* What is off-the-shelf?
|
||||
* What services depend on each other?
|
||||
* How is it administered?
|
||||
* Documenting guidelines and policies for how to run the infrastructure as a community.
|
||||
* What are our access policies?
|
||||
* How do we keep track of billing?
|
||||
* How do we ensure privacy and security?
|
||||
* Migrating infrastructure over to the CNCF as-is.
|
||||
* What is the path of least resistance to migration?
|
||||
* Improving the state of the infrastructure for sustainability.
|
||||
* Moving from humans running scripts to a more automated GitOps model (YAML all the things!)
|
||||
* Supporting community members who wish to develop new infrastructure
|
||||
* Documenting the state of our efforts, better defining goals, and completeness indicators.
|
||||
* The project and program management necessary to communicate this work to our [massive community of contributors](https://kubernetes.io/blog/2020/04/21/contributor-communication/)
|
||||
|
||||
## The challenge of K8s-Infrastructure is documentation
|
||||
|
||||
The most crucial problem the working group is trying to tackle is that the project is all volunteer-led. This leads to contributors, chairs, and others involved in the project quickly becoming overscheduled. As a result of this, certain areas such as documentation and organization often lack information, and efforts to progress are taking longer than the group would like to complete.
|
||||
|
||||
Some of the infrastructure that is being migrated over hasn't been updated in a while, and its original authors or directly responsible individuals have moved on from working on Kubernetes. While this is great from the perspective of the fact that the code was able to run untouched for a long period of time, from the perspective of trying to migrate, this makes it difficult to identify how to operate these components, and how to move these infrastructure pieces where they need to be effectively.
|
||||
|
||||
The lack of documentation is being addressed head-on by group member [Bart Smykla](https://twitter.com/bartsmykla), but there is a definite need for others to support. If you're looking for a way to [get involved](https://github.com/kubernetes/community/labels/wg%2Fk8s-infra) and learn the infrastructure, you can become a new contributor to the working group!
|
||||
|
||||
## Celebrating some Working Group wins
|
||||
|
||||
The team has made progress in the last few months that is well worth celebrating.
|
||||
|
||||
- The K8s-Infrastructure Working Group released an automated billing report that they start every meeting off by reviewing as a group.
|
||||
- DNS for k8s.io and kubernetes.io are also fully [community-owned](https://groups.google.com/g/kubernetes-dev/c/LZTYJorGh7c/m/u-ydk-yNEgAJ), with community members able to [file issues](https://github.com/kubernetes/k8s.io/issues/new?assignees=&labels=wg%2Fk8s-infra&template=dns-request.md&title=DNS+REQUEST%3A+%3Cyour-dns-record%3E) to manage records.
|
||||
- The container registry [k8s.gcr.io](https://github.com/kubernetes/k8s.io/tree/master/k8s.gcr.io) is also fully community-owned and available for all Kubernetes subprojects to use.
|
||||
- The Kubernetes [publishing-bot](https://github.com/kubernetes/publishing-bot) responsible for keeping k8s.io/kubernetes/staging repositories published to their own top-level repos (For example: [kubernetes/api](https://github.com/kubernetes/api)) runs on a community-owned cluster.
|
||||
- The gcsweb.k8s.io service used to provide anonymous access to GCS buckets for kubernetes artifacts runs on a community-owned cluster.
|
||||
- There is also an automated process of promoting all our container images. This includes a fully documented infrastructure, managed by the Kubernetes community, with automated processes for provisioning permissions.
|
||||
|
||||
These are just a few of the things currently happening in the K8s Infrastructure working group.
|
||||
|
||||
If you're interested in getting involved, be sure to join the [#wg-K8s-infra Slack Channel](https://app.slack.com/client/T09NY5SBT/CCK68P2Q2). Meetings are 60 minutes long, and are held every other Wednesday at 8:30 AM PT/16:30 UTC.
|
||||
|
||||
Join to help with the documentation, stay to learn about the amazing infrastructure supporting the Kubernetes community.
|
|
@ -0,0 +1,655 @@
|
|||
---
|
||||
title: "My exciting journey into Kubernetes’ history"
|
||||
date: 2020-05-28
|
||||
slug: kubernetes-history
|
||||
url: /blog/2020/05/my-exciting-journey-into-kubernetes-history
|
||||
---
|
||||
|
||||
**Author:** Sascha Grunert, SUSE Software Solutions
|
||||
|
||||
_Editor's note: Sascha is part of [SIG Release][0] and is working on many other
|
||||
different container runtime related topics. Feel free to reach him out on
|
||||
Twitter [@saschagrunert][1]._
|
||||
|
||||
[0]: https://github.com/kubernetes/sig-release
|
||||
[1]: https://twitter.com/saschagrunert
|
||||
|
||||
---
|
||||
|
||||
> A story of data science-ing 90,000 GitHub issues and pull requests by using
|
||||
> Kubeflow, TensorFlow, Prow and a fully automated CI/CD pipeline.
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Getting the Data](#getting-the-data)
|
||||
- [Exploring the Data](#exploring-the-data)
|
||||
- [Labels, Labels, Labels](#labels-labels-labels)
|
||||
- [Building the Machine Learning Model](#building-the-machine-learning-model)
|
||||
- [Doing some first Natural Language Processing (NLP)](#doing-some-first-natural-language-processing-nlp)
|
||||
- [Creating the Multi-Layer Perceptron (MLP) Model](#creating-the-multi-layer-perceptron-mlp-model)
|
||||
- [Training the Model](#training-the-model)
|
||||
- [A first Prediction](#a-first-prediction)
|
||||
- [Automate Everything](#automate-everything)
|
||||
- [Automatic Labeling of new PRs](#automatic-labeling-of-new-prs)
|
||||
- [Summary](#summary)
|
||||
|
||||
# Introduction
|
||||
|
||||
Choosing the right steps when working in the field of data science is truly no
|
||||
silver bullet. Most data scientists might have their custom workflow, which
|
||||
could be more or less automated, depending on their area of work. Using
|
||||
[Kubernetes][10] can be a tremendous enhancement when trying to automate
|
||||
workflows on a large scale. In this blog post, I would like to take you on my
|
||||
journey of doing data science while integrating the overall workflow into
|
||||
Kubernetes.
|
||||
|
||||
The target of the research I did in the past few months was to find any
|
||||
useful information about all those thousands of GitHub issues and pull requests
|
||||
(PRs) we have in the [Kubernetes repository][11]. What I ended up with was a
|
||||
fully automated, in Kubernetes running Continuous Integration (CI) and
|
||||
Deployment (CD) data science workflow powered by [Kubeflow][12] and [Prow][13].
|
||||
You may not know both of them, but we get to the point where I explain what
|
||||
they’re doing in detail. The source code of my work can be found in the
|
||||
[kubernetes-analysis GitHub repository][14], which contains everything source
|
||||
code-related as well as the raw data. But how to retrieve this data I’m talking
|
||||
about? Well, this is where the story begins.
|
||||
|
||||
[10]: https://kubernetes.io
|
||||
[11]: https://github.com/kubernetes/kubernetes
|
||||
[12]: https://www.kubeflow.org
|
||||
[13]: https://github.com/kubernetes/test-infra/tree/master/prow
|
||||
[14]: https://github.com/kubernetes-analysis/kubernetes-analysis
|
||||
|
||||
# Getting the Data
|
||||
|
||||
The foundation for my experiments is the raw GitHub API data in plain [JSON][23]
|
||||
format. The necessary data can be retrieved via the [GitHub issues
|
||||
endpoint][20], which returns all pull requests as well as regular issues in the
|
||||
[REST][21] API. I exported roughly **91000** issues and pull requests in
|
||||
the first iteration into a massive **650 MiB** data blob. This took me about **8
|
||||
hours** of data retrieval time because for sure, the GitHub API is [rate
|
||||
limited][22]. To be able to put this data into a GitHub repository, I’d chosen
|
||||
to compress it via [`xz(1)`][24]. The result was a roundabout [25 MiB sized
|
||||
tarball][25], which fits well into the repository.
|
||||
|
||||
[20]: https://developer.github.com/v3/issues
|
||||
[21]: https://en.wikipedia.org/wiki/Representational_state_transfer
|
||||
[22]: https://developer.github.com/apps/building-github-apps/understanding-rate-limits-for-github-apps/
|
||||
[23]: https://en.wikipedia.org/wiki/JSON
|
||||
[24]: https://linux.die.net/man/1/xz
|
||||
[25]: https://github.com/kubernetes-analysis/kubernetes-analysis/blob/master/data/api.tar.xz
|
||||
|
||||
I had to find a way to regularly update the dataset because the Kubernetes
|
||||
issues and pull requests are updated by the users over time as well as new ones
|
||||
are created. To achieve the continuous update without having to wait 8 hours
|
||||
over and over again, I now fetch the delta GitHub API data between the
|
||||
[last update][31] and the current time. This way, a Continuous Integration job
|
||||
can update the data on a regular basis, whereas I can continue my research with
|
||||
the latest available set of data.
|
||||
|
||||
From a tooling perspective, I’ve written an [all-in-one Python executable][30],
|
||||
which allows us to trigger the different steps during the data science
|
||||
experiments separately via dedicated subcommands. For example, to run an export
|
||||
of the whole data set, we can call:
|
||||
|
||||
[30]: https://github.com/kubernetes-analysis/kubernetes-analysis/blob/master/main
|
||||
[31]: https://github.com/kubernetes-analysis/kubernetes-analysis/blob/master/.update
|
||||
|
||||
```
|
||||
> export GITHUB_TOKEN=<MY-SECRET-TOKEN>
|
||||
> ./main export
|
||||
INFO | Getting GITHUB_TOKEN from environment variable
|
||||
INFO | Dumping all issues
|
||||
INFO | Pulling 90929 items
|
||||
INFO | 1: Unit test coverage in Kubelet is lousy. (~30%)
|
||||
INFO | 2: Better error messages if go isn't installed, or if gcloud is old.
|
||||
INFO | 3: Need real cluster integration tests
|
||||
INFO | 4: kubelet should know which containers it is managing
|
||||
… [just wait 8 hours] …
|
||||
```
|
||||
|
||||
To update the data between the last time stamp stored in the repository we can
|
||||
run:
|
||||
|
||||
```
|
||||
> ./main export --update-api
|
||||
INFO | Getting GITHUB_TOKEN from environment variable
|
||||
INFO | Retrieving issues and PRs
|
||||
INFO | Updating API
|
||||
INFO | Got update timestamp: 2020-05-09T10:57:40.854151
|
||||
INFO | 90786: Automated cherry pick of #90749: fix: azure disk dangling attach issue
|
||||
INFO | 90674: Switch core master base images from debian to distroless
|
||||
INFO | 90086: Handling error returned by request.Request.ParseForm()
|
||||
INFO | 90544: configurable weight on the CPU and memory
|
||||
INFO | 87746: Support compiling Kubelet w/o docker/docker
|
||||
INFO | Using already extracted data from data/data.pickle
|
||||
INFO | Loading pickle dataset
|
||||
INFO | Parsed 34380 issues and 55832 pull requests (90212 items)
|
||||
INFO | Updating data
|
||||
INFO | Updating issue 90786 (updated at 2020-05-09T10:59:43Z)
|
||||
INFO | Updating issue 90674 (updated at 2020-05-09T10:58:27Z)
|
||||
INFO | Updating issue 90086 (updated at 2020-05-09T10:58:26Z)
|
||||
INFO | Updating issue 90544 (updated at 2020-05-09T10:57:51Z)
|
||||
INFO | Updating issue 87746 (updated at 2020-05-09T11:01:51Z)
|
||||
INFO | Saving data
|
||||
```
|
||||
|
||||
This gives us an idea of how fast the project is actually moving: On a Saturday
|
||||
at noon (European time), 5 issues and pull requests got updated within literally 5
|
||||
minutes!
|
||||
|
||||
Funnily enough, [Joe Beda][32], one of the founders of Kubernetes, created the
|
||||
first GitHub issue [mentioning that the unit test coverage is too low][33]. The
|
||||
issue has no further description than the title, and no enhanced labeling
|
||||
applied, like we know from more recent issues and pull requests. But now we have
|
||||
to explore the exported data more deeply to do something useful with it.
|
||||
|
||||
[32]: https://github.com/jbeda
|
||||
[33]: https://github.com/kubernetes/kubernetes/issues/1
|
||||
|
||||
# Exploring the Data
|
||||
|
||||
Before we can start creating machine learning models and train them, we have to
|
||||
get an idea about how our data is structured and what we want to achieve in
|
||||
general.
|
||||
|
||||
To get a better feeling about the amount of data, let’s look at how many issues
|
||||
and pull requests have been created over time inside the Kubernetes repository:
|
||||
|
||||
```
|
||||
> ./main analyze --created
|
||||
INFO | Using already extracted data from data/data.pickle
|
||||
INFO | Loading pickle dataset
|
||||
INFO | Parsed 34380 issues and 55832 pull requests (90212 items)
|
||||
```
|
||||
|
||||
The Python [matplotlib][40] module should pop up a graph which looks like this:
|
||||
|
||||
![created all](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/created-all.svg)
|
||||
|
||||
[40]: https://matplotlib.org
|
||||
|
||||
Okay, this looks not that spectacular but gives us an impression on how the
|
||||
project has grown over the past 6 years. To get a better idea about the speed of
|
||||
development of the project, we can look at the _created-vs-closed_ metric. This
|
||||
means on our timeline, we add one to the y-axis if an issue or pull request got
|
||||
created and subtracts one if closed. Now the chart looks like this:
|
||||
|
||||
```
|
||||
> ./main analyze --created-vs-closed
|
||||
```
|
||||
|
||||
![created vs closed all](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/created-vs-closed-all.svg)
|
||||
|
||||
At the beginning of 2018, the Kubernetes projects introduced some more enhanced
|
||||
life-cycle management via the glorious [fejta-bot][41]. This automatically
|
||||
closes issues and pull requests after they got stale over a longer period of
|
||||
time. This resulted in a massive closing of issues, which does not apply to pull
|
||||
requests in the same amount. For example, if we look at the _created-vs-closed_
|
||||
metric only for pull requests.
|
||||
|
||||
[41]: https://github.com/fejta-bot
|
||||
|
||||
```
|
||||
> ./main analyze --created-vs-closed --pull-requests
|
||||
```
|
||||
|
||||
![created vs closed pull requests](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/created-vs-closed-pull-requests.svg)
|
||||
|
||||
The overall impact is not that obvious. What we can see is that the increasing
|
||||
number of peaks in the PR chart indicates that the project is moving faster over
|
||||
time. Usually, a candlestick chart would be a better choice for showing this kind
|
||||
of volatility-related information. I’d also like to highlight that it looks like
|
||||
the development of the project slowed down a bit in the beginning of 2020.
|
||||
|
||||
Parsing raw JSON in every analysis iteration is not the fastest approach to do
|
||||
in Python. This means that I decided to parse the more important information,
|
||||
for example the content, title and creation time into dedicated [issue][50] and
|
||||
[PR classes][51]. This data will be [pickle][58] serialized into the repository
|
||||
as well, which allows an overall faster startup independently of the JSON blob.
|
||||
|
||||
A pull request is more or less the same as an issue in my analysis, except that
|
||||
it contains a release note.
|
||||
|
||||
[50]: https://github.com/kubernetes-analysis/kubernetes-analysis/blob/master/src/issue.py
|
||||
[51]: https://github.com/kubernetes-analysis/kubernetes-analysis/blob/master/src/pull_request.py
|
||||
[58]: https://docs.python.org/3/library/pickle.html
|
||||
|
||||
Release notes in Kubernetes are written in the PRs description into a separate
|
||||
`release-note` block like this:
|
||||
|
||||
````
|
||||
```release-note
|
||||
I changed something extremely important and you should note that.
|
||||
```
|
||||
````
|
||||
|
||||
Those release notes are parsed by [dedicated Release Engineering Tools like
|
||||
`krel`][52] during the release creation process and will be part of the various
|
||||
[CHANGELOG.md][53] files and the [Release Notes Website][54]. That seems like a
|
||||
lot of magic, but in the end, the quality of the overall release notes is much
|
||||
higher because they’re easy to edit, and the PR reviewers can ensure that we
|
||||
only document real user-facing changes and nothing else.
|
||||
|
||||
[52]: https://github.com/kubernetes/release#tools
|
||||
[53]: https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG
|
||||
[54]: https://relnotes.k8s.io
|
||||
|
||||
The quality of the input data is a key aspect when doing data science. I decided
|
||||
to focus on the release notes because they seem to have the highest amount of
|
||||
overall quality when comparing them to the plain descriptions in issues and PRs.
|
||||
Besides that, they’re easy to parse, and we would not need to strip away
|
||||
the [various issue][55] and [PR template][56] text noise.
|
||||
|
||||
[55]: https://github.com/kubernetes/kubernetes/tree/master/.github/ISSUE_TEMPLATE
|
||||
[56]: https://github.com/kubernetes/kubernetes/blob/master/.github/PULL_REQUEST_TEMPLATE.md
|
||||
|
||||
## Labels, Labels, Labels
|
||||
|
||||
Issues and pull requests in Kubernetes get different labels applied during its
|
||||
life-cycle. They are usually grouped via a single slash (`/`). For example, we
|
||||
have `kind/bug` and `kind/api-change` or `sig/node` and `sig/network`. An easy
|
||||
way to understand which label groups exist and how they’re distributed across
|
||||
the repository is to plot them into a bar chart:
|
||||
|
||||
```
|
||||
> ./main analyze --labels-by-group
|
||||
```
|
||||
|
||||
![labels by group all top 25](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/labels-by-group-all-top-25.svg)
|
||||
|
||||
It looks like that `sig/`, `kind/` and `area/` labels are pretty common.
|
||||
Something like `size/` can be ignored for now because these labels are
|
||||
automatically applied based on the amount of the code changes for a pull
|
||||
request. We said that we want to focus on release notes as input data, which
|
||||
means that we have to check out the distribution of the labels for the PRs. This
|
||||
means that the top 25 labels on pull requests are:
|
||||
|
||||
```
|
||||
> ./main analyze --labels-by-name --pull-requests
|
||||
```
|
||||
|
||||
![labels by name pull requests top 25](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/labels-by-name-pull-requests-top-25.svg)
|
||||
|
||||
Again, we can ignore labels like `lgtm` (looks good to me), because every PR
|
||||
which now should get merged has to look good. Pull requests containing release
|
||||
notes automatically get the `release-note` label applied, which enables further
|
||||
filtering more easily. This does not mean that every PR containing that label
|
||||
also contains the release notes block. The label could have been applied
|
||||
manually and the parsing of the release notes block did not exist since the
|
||||
beginning of the project. This means we will probably loose a decent amount of
|
||||
input data on one hand. On the other hand we can focus on the highest possible
|
||||
data quality, because applying labels the right way needs some enhanced maturity
|
||||
of the project and its contributors.
|
||||
|
||||
From a label group perspective I have chosen to focus on the `kind/` labels.
|
||||
Those labels are something which has to be applied manually by the author of the
|
||||
PR, they are available on a good amount of pull requests and they’re related to
|
||||
user-facing changes as well. Besides that, the `kind/` choice has to be done for
|
||||
every pull request because it is part of the PR template.
|
||||
|
||||
Alright, how does the distribution of those labels look like when focusing only
|
||||
on pull requests which have release notes?
|
||||
|
||||
```
|
||||
> ./main analyze --release-notes-stats
|
||||
```
|
||||
|
||||
![release notes stats](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/release-notes-stats.svg)
|
||||
|
||||
Interestingly, we have approximately 7,000 overall pull requests containing
|
||||
release notes, but only ~5,000 have a `kind/` label applied. The distribution of
|
||||
the labels is not equal, and one-third of them are labeled as `kind/bug`. This
|
||||
brings me to the next decision in my data science journey: I will build a binary
|
||||
classifier which, for the sake of simplicity, is only able to distinguish between
|
||||
bugs (via `kind/bug`) and non-bugs (where the label is not applied).
|
||||
|
||||
The main target is now to be able to classify newly incoming release notes if
|
||||
they are related to a bug or not, based on the historical data we already have
|
||||
from the community.
|
||||
|
||||
Before doing that, I recommend that you play around with the `./main analyze -h`
|
||||
subcommand as well to explore the latest set of data. You can also check out all
|
||||
the [continuously updated assets][57] I provide within the analysis repository.
|
||||
For example, those are the top 25 PR creators inside the Kubernetes repository:
|
||||
|
||||
![users by created pull request](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/users-by-created-pull-requests-top-25.svg)
|
||||
|
||||
[57]: https://github.com/kubernetes-analysis/kubernetes-analysis/tree/master/assets
|
||||
|
||||
# Building the Machine Learning Model
|
||||
|
||||
Now we have an idea what the data set is about, and we can start building a first
|
||||
machine learning model. Before actually building the model, we have to
|
||||
pre-process all the extracted release notes from the PRs. Otherwise, the model
|
||||
would not be able to understand our input.
|
||||
|
||||
## Doing some first Natural Language Processing (NLP)
|
||||
|
||||
In the beginning, we have to define a vocabulary for which we want to train. I
|
||||
decided to choose the [TfidfVectorizer][60] from the Python scikit-learn machine
|
||||
learning library. This vectorizer is able to take our input texts and create a
|
||||
single huge vocabulary out of it. This is our so-called [bag-of-words][61],
|
||||
which has a chosen n-gram range of `(1, 2)` (unigrams and bigrams). Practically
|
||||
this means that we always use the first word and the next one as a single
|
||||
vocabulary entry (bigrams). We also use the single word as vocabulary entry
|
||||
(unigram). The TfidfVectorizer is able to skip words that occur multiple times
|
||||
(`max_df`), and requires a minimum amount (`min_df`) to add a word to the
|
||||
vocabulary. I decided not to change those values in the first place, just
|
||||
because I had the intuition that release notes are something unique to a
|
||||
project.
|
||||
|
||||
Parameters like `min_df`, `max_df` and the n-gram range can be seen as some of
|
||||
our hyperparameters. Those parameters have to be optimized in a dedicated step
|
||||
after the machine learning model has been built. This step is called
|
||||
hyperparameter tuning and basically means that we train multiple times with
|
||||
different parameters and compare the accuracy of the model. Afterwards, we choose
|
||||
the parameters with the best accuracy.
|
||||
|
||||
[60]: https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html
|
||||
[61]: https://en.wikipedia.org/wiki/Bag-of-words_model
|
||||
|
||||
During the training, the vectorizer will produce a `data/features.json` which
|
||||
contains the whole vocabulary. This gives us a good understanding of how such a
|
||||
vocabulary may look like:
|
||||
|
||||
```json
|
||||
[
|
||||
…
|
||||
"hostname",
|
||||
"hostname address",
|
||||
"hostname and",
|
||||
"hostname as",
|
||||
"hostname being",
|
||||
"hostname bug",
|
||||
…
|
||||
]
|
||||
```
|
||||
|
||||
This produces round about 50,000 entries in the overall bag-of-words, which is
|
||||
pretty much. Previous analyses between different data sets showed that it is
|
||||
simply not necessary to take so many features into account. Some general data
|
||||
sets state that an overall vocabulary of 20,000 is enough and higher amounts do
|
||||
not influence the accuracy any more. To do so we can use the [SelectKBest][62]
|
||||
feature selector to strip down the vocabulary to only choose the top features.
|
||||
Anyway, I still decided to stick to the top 50,000 to not negatively influence
|
||||
the model accuracy. We have a relatively low amount of data (appr. 7,000
|
||||
samples) and a low number of words per sample (~15) which already made me wonder
|
||||
if we have enough data at all.
|
||||
|
||||
[62]: https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectKBest.html
|
||||
|
||||
The vectorizer is not only able to create our bag-of-words, but it is also able to
|
||||
encode the features in [term frequency–inverse document frequency (tf-idf)][63]
|
||||
format. That is where the vectorizer got its name, whereas the output of that
|
||||
encoding is something the machine learning model can directly consume. All the
|
||||
details of the vectorization process can be found in the [source code][64].
|
||||
|
||||
[63]: https://en.wikipedia.org/wiki/Tf%e2%80%93idf
|
||||
[64]: https://github.com/kubernetes-analysis/kubernetes-analysis/blob/f419ff4a3462bafc0cb067aa6973dc7280409699/src/nlp.py#L193-L235
|
||||
|
||||
## Creating the Multi-Layer Perceptron (MLP) Model
|
||||
|
||||
I decided to choose a simple MLP based model which is built with the help of the
|
||||
popular [TensorFlow][70] framework. Because we do not have that much input data,
|
||||
we just use two hidden layers, so that the model basically looks like this:
|
||||
|
||||
![model](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/model.png)
|
||||
|
||||
[70]: https://www.tensorflow.org/api_docs/python/tf/keras
|
||||
|
||||
There have to be [multiple other][71] hyperparameters to be taken into account
|
||||
when creating the model. I will not discuss them in detail here, but they’re
|
||||
important to be optimized also in relation to the number of classes we want to
|
||||
have in the model (only two in our case).
|
||||
|
||||
[71]: https://github.com/kubernetes-analysis/kubernetes-analysis/blob/f419ff4a3462bafc0cb067aa6973dc7280409699/src/nlp.py#L95-L100
|
||||
|
||||
## Training the Model
|
||||
|
||||
Before starting the actual training, we have to split up our input data into
|
||||
training and validation data sets. I’ve chosen to use ~80% of the data for
|
||||
training and 20% for validation purposes. We have to shuffle our input data as
|
||||
well to ensure that the model is not affected by ordering issues. The technical
|
||||
details of the training process can be found in the [GitHub sources][80]. So now
|
||||
we’re ready to finally start the training:
|
||||
|
||||
```
|
||||
> ./main train
|
||||
INFO | Using already extracted data from data/data.pickle
|
||||
INFO | Loading pickle dataset
|
||||
INFO | Parsed 34380 issues and 55832 pull requests (90212 items)
|
||||
INFO | Training for label 'kind/bug'
|
||||
INFO | 6980 items selected
|
||||
INFO | Using 5584 training and 1395 testing texts
|
||||
INFO | Number of classes: 2
|
||||
INFO | Vocabulary len: 51772
|
||||
INFO | Wrote features to file data/features.json
|
||||
INFO | Using units: 1
|
||||
INFO | Using activation function: sigmoid
|
||||
INFO | Created model with 2 layers and 64 units
|
||||
INFO | Compiling model
|
||||
INFO | Starting training
|
||||
Train on 5584 samples, validate on 1395 samples
|
||||
Epoch 1/1000
|
||||
5584/5584 - 3s - loss: 0.6895 - acc: 0.6789 - val_loss: 0.6856 - val_acc: 0.6860
|
||||
Epoch 2/1000
|
||||
5584/5584 - 2s - loss: 0.6822 - acc: 0.6827 - val_loss: 0.6782 - val_acc: 0.6860
|
||||
Epoch 3/1000
|
||||
…
|
||||
Epoch 68/1000
|
||||
5584/5584 - 2s - loss: 0.2587 - acc: 0.9257 - val_loss: 0.4847 - val_acc: 0.7728
|
||||
INFO | Confusion matrix:
|
||||
[[920 32]
|
||||
[291 152]]
|
||||
INFO | Confusion matrix normalized:
|
||||
[[0.966 0.034]
|
||||
[0.657 0.343]]
|
||||
INFO | Saving model to file data/model.h5
|
||||
INFO | Validation accuracy: 0.7727598547935486, loss: 0.48470408514836355
|
||||
```
|
||||
|
||||
The output of the [Confusion Matrix][81] shows us that we’re pretty good on
|
||||
training accuracy, but the validation accuracy could be a bit higher. We now
|
||||
could start a hyperparameter tuning to see if we can optimize the output of the
|
||||
model even further. I will leave that experiment up to you with the hint to the
|
||||
`./main train --tune` flag.
|
||||
|
||||
We saved the model (`data/model.h5`), the vectorizer (`data/vectorizer.pickle`)
|
||||
and the feature selector (`data/selector.pickle`) to disk to be able to use them
|
||||
later on for prediction purposes without having a need for additional training
|
||||
steps.
|
||||
|
||||
[80]: https://github.com/kubernetes-analysis/kubernetes-analysis/blob/f419ff4a3462bafc0cb067aa6973dc7280409699/src/nlp.py#L91-L170
|
||||
[81]: https://en.wikipedia.org/wiki/Confusion_matrix
|
||||
|
||||
## A first Prediction
|
||||
|
||||
We are now able to test the model by loading it from disk and predicting some
|
||||
input text:
|
||||
|
||||
```
|
||||
> ./main predict --test
|
||||
INFO | Testing positive text:
|
||||
|
||||
Fix concurrent map access panic
|
||||
Don't watch .mount cgroups to reduce number of inotify watches
|
||||
Fix NVML initialization race condition
|
||||
Fix brtfs disk metrics when using a subdirectory of a subvolume
|
||||
|
||||
INFO | Got prediction result: 0.9940581321716309
|
||||
INFO | Matched expected positive prediction result
|
||||
INFO | Testing negative text:
|
||||
|
||||
action required
|
||||
1. Currently, if users were to explicitly specify CacheSize of 0 for
|
||||
KMS provider, they would end-up with a provider that caches up to
|
||||
1000 keys. This PR changes this behavior.
|
||||
Post this PR, when users supply 0 for CacheSize this will result in
|
||||
a validation error.
|
||||
2. CacheSize type was changed from int32 to *int32. This allows
|
||||
defaulting logic to differentiate between cases where users
|
||||
explicitly supplied 0 vs. not supplied any value.
|
||||
3. KMS Provider's endpoint (path to Unix socket) is now validated when
|
||||
the EncryptionConfiguration files is loaded. This used to be handled
|
||||
by the GRPCService.
|
||||
|
||||
INFO | Got prediction result: 0.1251964420080185
|
||||
INFO | Matched expected negative prediction result
|
||||
```
|
||||
|
||||
Both tests are real-world examples which already exist. We could also try
|
||||
something completely different, like this random tweet I found a couple of
|
||||
minutes ago:
|
||||
|
||||
```
|
||||
./main predict "My dudes, if you can understand SYN-ACK, you can understand consent"
|
||||
INFO | Got prediction result: 0.1251964420080185
|
||||
ERROR | Result is lower than selected threshold 0.6
|
||||
```
|
||||
|
||||
Looks like it is not classified as bug for a release note, which seems to work.
|
||||
Selecting a good threshold is also not that easy, but sticking to something >
|
||||
50% should be the bare minimum.
|
||||
|
||||
# Automate Everything
|
||||
|
||||
The next step is to find some way of automation to continuously update the model
|
||||
with new data. If I change any source code within my repository, then I’d like
|
||||
to get feedback about the test results of the model without having a need to run
|
||||
the training on my own machine. I would like to utilize the GPUs in my
|
||||
Kubernetes cluster to train faster and automatically update the data set if a PR
|
||||
got merged.
|
||||
|
||||
With the help of [Kubeflow pipelines][90] we can fulfill most of these
|
||||
requirements. The pipeline I built looks like this:
|
||||
|
||||
[90]: https://www.kubeflow.org/docs/pipelines/overview/pipelines-overview
|
||||
|
||||
![pipeline](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/kubeflow-pipeline.png)
|
||||
|
||||
First, we check out the source code of the PR, which will be passed on as output
|
||||
artifact to all other steps. Then we incrementally update the API and internal
|
||||
data before we run the training on an always up-to-date data set. The prediction
|
||||
test verifies after the training that we did not badly influence the model with
|
||||
our changes.
|
||||
|
||||
We also built a container image within our pipeline. [This container image][91]
|
||||
copies the previously built model, vectorizer, and selector into a container and
|
||||
runs `./main serve`. When doing this, we spin up a [kfserving][92] web server,
|
||||
which can be used for prediction purposes. Do you want to try it out by yourself? Simply
|
||||
do a JSON POST request like this and run the prediction against the endpoint:
|
||||
|
||||
```
|
||||
> curl https://kfserving.k8s.saschagrunert.de/v1/models/kubernetes-analysis:predict \
|
||||
-d '{"text": "my test text"}'
|
||||
{"result": 0.1251964420080185}
|
||||
```
|
||||
|
||||
The [custom kfserving][93] implementation is pretty straightforward, whereas the
|
||||
deployment utilizes [Knative Serving][95] and an [Istio][94] ingress gateway
|
||||
under the hood to correctly route the traffic into the cluster and provide the
|
||||
right set of services.
|
||||
|
||||
[91]: https://github.com/kubernetes-analysis/kubernetes-analysis/blob/master/Dockerfile-deploy
|
||||
[92]: https://www.kubeflow.org/docs/components/serving/kfserving
|
||||
[93]: https://github.com/kubernetes-analysis/kubernetes-analysis/blob/master/src/kfserver.py
|
||||
[94]: https://istio.io
|
||||
[95]: https://knative.dev/docs/serving
|
||||
|
||||
The `commit-changes` and `rollout` step will only run if the pipeline runs on
|
||||
the `master` branch. Those steps make sure that we always have the latest data
|
||||
set available on the master branch as well as in the kfserving deployment. The
|
||||
[rollout step][96] creates a new canary deployment, which only accepts 50% of the
|
||||
incoming traffic in the first place. After the canary got deployed successfully,
|
||||
it will be promoted as the new main instance of the service. This is a great way
|
||||
to ensure that the deployment works as intended and allows additional testing
|
||||
after rolling out the canary.
|
||||
|
||||
[96]: https://github.com/kubernetes-analysis/kubernetes-analysis/blob/f419ff4a3462bafc0cb067aa6973dc7280409699/src/rollout.py#L30-L51
|
||||
|
||||
But how to trigger Kubeflow pipelines when creating a pull request? Kubeflow has
|
||||
no feature for that right now. That’s why I decided to use [Prow][100],
|
||||
Kubernetes test-infrastructure project for CI/CD purposes.
|
||||
|
||||
First of all, a [24h periodic job][101] ensures that we have at least daily
|
||||
up-to-date data available within the repository. Then, if we create a pull
|
||||
request, Prow will run the whole Kubeflow pipeline without committing or rolling
|
||||
out any changes. If we merge the pull request via Prow, another job runs on the
|
||||
master and updates the data as well as the deployment. That’s pretty neat, isn’t
|
||||
it?
|
||||
|
||||
[100]: https://github.com/kubernetes/test-infra/tree/master/prow
|
||||
[101]: https://github.com/kubernetes-analysis/kubernetes-analysis/blob/f419ff4a3462bafc0cb067aa6973dc7280409699/ci/config.yaml#L45-L61
|
||||
|
||||
# Automatic Labeling of new PRs
|
||||
|
||||
The prediction API is nice for testing, but now we need a real-world use case.
|
||||
Prow supports external plugins which can be used to take action on any GitHub
|
||||
event. I wrote [a plugin][110] which uses the kfserving API to make predictions
|
||||
based on new pull requests. This means if we now create a new pull request in
|
||||
the kubernetes-analysis repository, we will see the following:
|
||||
|
||||
[110]: https://github.com/kubernetes-analysis/kubernetes-analysis/tree/master/pkg
|
||||
|
||||
![pr 1](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/pr-1.png)
|
||||
|
||||
---
|
||||
|
||||
![pr 2](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/pr-2.png)
|
||||
|
||||
Okay cool, so now let’s change the release note based on a real bug from the
|
||||
already existing dataset:
|
||||
|
||||
![pr 3](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/pr-3.png)
|
||||
|
||||
---
|
||||
|
||||
![pr 4](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/pr-4.png)
|
||||
|
||||
The bot edits its own comment, predicts it with round about 90% as `kind/bug`
|
||||
and automatically adds the correct label! Now, if we change it back to some
|
||||
different - obviously wrong - release note:
|
||||
|
||||
![pr 5](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/pr-5.png)
|
||||
|
||||
---
|
||||
|
||||
![pr 6](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/pr-6.png)
|
||||
|
||||
The bot does the work for us, removes the label and informs us what it did!
|
||||
Finally, if we change the release note to `None`:
|
||||
|
||||
![pr 7](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/pr-7.png)
|
||||
|
||||
---
|
||||
|
||||
![pr 8](/images/blog/2020-05-28-my-exciting-journey-into-kubernetes-history/pr-8.png)
|
||||
|
||||
The bot removed the comment, which is nice and reduces the text noise on the PR.
|
||||
Everything I demonstrated is running inside a single Kubernetes cluster, which
|
||||
would make it unnecessary at all to expose the kfserving API to the public. This
|
||||
introduces an indirect API rate limiting because the only usage would be
|
||||
possible via the Prow bot user.
|
||||
|
||||
If you want to try it out for yourself, feel free to open a [new test
|
||||
issue][111] in `kubernetes-analysis`. This works because I enabled the plugin
|
||||
also for issues rather than only for pull requests.
|
||||
|
||||
[111]: https://github.com/kubernetes-analysis/kubernetes-analysis/issues/new?&template=release-notes-test.md
|
||||
|
||||
So then, we have a running CI bot which is able to classify new release notes
|
||||
based on a machine learning model. If the bot would run in the official
|
||||
Kubernetes repository, then we could correct wrong label predictions manually.
|
||||
This way, the next training iteration would pick up the correction and result in
|
||||
a continuously improved model over time. All totally automated!
|
||||
|
||||
# Summary
|
||||
|
||||
Thank you for reading down to here! This was my little data science journey
|
||||
through the Kubernetes GitHub repository. There are a lot of other things to
|
||||
optimize, for example introducing more classes (than just `kind/bug` or nothing)
|
||||
or automatic hyperparameter tuning with Kubeflows [Katib][120]. If you have any
|
||||
questions or suggestions, then feel free to get in touch with me anytime. See you
|
||||
soon!
|
||||
|
||||
[120]: https://www.kubeflow.org/docs/components/hyperparameter-tuning/hyperparameter
|
|
@ -0,0 +1,201 @@
|
|||
---
|
||||
layout: blog
|
||||
title: "K8s KPIs with Kuberhealthy"
|
||||
date: 2020-05-29
|
||||
---
|
||||
|
||||
**Authors:** Joshulyne Park (Comcast), Eric Greer (Comcast)
|
||||
|
||||
### Building Onward from Kuberhealthy v2.0.0
|
||||
|
||||
Last November at KubeCon San Diego 2019, we announced the release of
|
||||
[Kuberhealthy 2.0.0](https://www.youtube.com/watch?v=aAJlWhBtzqY) - transforming Kuberhealthy into a Kubernetes operator
|
||||
for synthetic monitoring. This new ability granted developers the means to create their own Kuberhealthy check
|
||||
containers to synthetically monitor their applications and clusters. The community was quick to adopt this new feature and we're grateful for everyone who implemented and tested Kuberhealthy 2.0.0 in their clusters. Thanks to all of you who reported
|
||||
issues and contributed to discussions on the #kuberhealthy Slack channel. We quickly set to work to address all your feedback
|
||||
with a newer version of Kuberhealthy. Additionally, we created a guide on how to easily install and use Kuberhealthy in order to capture some helpful synthetic [KPIs](https://kpi.org/KPI-Basics).
|
||||
|
||||
### Deploying Kuberhealthy
|
||||
|
||||
To install Kuberhealthy, make sure you have [Helm 3](https://helm.sh/docs/intro/install/) installed. If not, you can use the generated flat spec files located
|
||||
in this [deploy folder](https://github.com/Comcast/kuberhealthy/tree/master/deploy). You should use [kuberhealthy-prometheus.yaml](https://github.com/Comcast/kuberhealthy/blob/master/deploy/kuberhealthy-prometheus.yaml) if you don't use the [Prometheus Operator](https://github.com/coreos/prometheus-operator), and [kuberhealthy-prometheus-operator.yaml](https://github.com/Comcast/kuberhealthy/blob/master/deploy/kuberhealthy-prometheus-operator.yaml) if you do. If you don't use Prometheus at all, you can still use Kuberhealthy with a JSON status page and/or InfluxDB integration using [this spec](https://github.com/Comcast/kuberhealthy/blob/master/deploy/kuberhealthy.yaml).
|
||||
|
||||
#### To install using Helm 3:
|
||||
##### 1. Create namespace "kuberhealthy" in the desired Kubernetes cluster/context:
|
||||
```
|
||||
kubectl create namespace kuberhealthy
|
||||
```
|
||||
##### 2. Set your current namespace to "kuberhealthy":
|
||||
```
|
||||
kubectl config set-context --current --namespace=kuberhealthy
|
||||
```
|
||||
##### 3. Add the kuberhealthy repo to Helm:
|
||||
```
|
||||
helm repo add kuberhealthy https://comcast.github.io/kuberhealthy/helm-repos
|
||||
```
|
||||
##### 4. Depending on your Prometheus implementation, install Kuberhealthy using the appropriate command for your cluster:
|
||||
|
||||
- If you use the [Prometheus Operator](https://github.com/coreos/prometheus-operator):
|
||||
```
|
||||
helm install kuberhealthy kuberhealthy/kuberhealthy --set prometheus.enabled=true,prometheus.enableAlerting=true,prometheus.enableScraping=true,prometheus.serviceMonitor=true
|
||||
```
|
||||
|
||||
- If you use Prometheus, but NOT Prometheus Operator:
|
||||
```
|
||||
helm install kuberhealthy kuberhealthy/kuberhealthy --set prometheus.enabled=true,prometheus.enableAlerting=true,prometheus.enableScraping=true
|
||||
```
|
||||
See additional details about configuring the appropriate scrape annotations in the section [Prometheus Integration Details](#prometheus-integration-details) below.
|
||||
|
||||
- Finally, if you don't use Prometheus:
|
||||
```
|
||||
helm install kuberhealthy kuberhealthy/kuberhealthy
|
||||
```
|
||||
|
||||
Running the Helm command should automatically install the newest version of Kuberhealthy (v2.2.0) along with a few basic checks. If you run `kubectl get pods`, you should see two Kuberhealthy pods. These are the pods that create, coordinate, and track test pods. These two Kuberhealthy pods also serve a JSON status page as well as a `/metrics` endpoint. Every other pod you see created is a checker pod designed to execute and shut down when done.
|
||||
|
||||
### Configuring Additional Checks
|
||||
|
||||
Next, you can run `kubectl get khchecks`. You should see three Kuberhealthy checks installed by default:
|
||||
- [daemonset](https://github.com/Comcast/kuberhealthy/tree/master/cmd/daemonset-check): Deploys and tears down a daemonset to ensure all nodes in the cluster are functional.
|
||||
- [deployment](https://github.com/Comcast/kuberhealthy/tree/master/cmd/deployment-check): Creates a deployment and then triggers a rolling update. Tests that the deployment is reachable via a service and then deletes everything. Any problem in this process will cause this check to report a failure.
|
||||
- [dns-status-internal](https://github.com/Comcast/kuberhealthy/tree/master/cmd/dns-resolution-check): Validates that internal cluster DNS is functioning as expected.
|
||||
|
||||
To view other available external checks, check out the [external checks registry](https://github.com/Comcast/kuberhealthy/blob/master/docs/EXTERNAL_CHECKS_REGISTRY.md) where you can find other yaml files you can apply to your cluster to enable various checks.
|
||||
|
||||
Kuberhealthy check pods should start running shortly after Kuberhealthy starts running (1-2 minutes). Additionally, the check-reaper cronjob runs every few minutes to ensure there are no more than 5 completed checker pods left lying around at a time.
|
||||
|
||||
To get status page view of these checks, you'll need to either expose the `kuberhealthy` service externally by editing the service `kuberhealthy` and setting `Type: LoadBalancer` or use `kubectl port-forward service/kuberhealthy 8080:80`. When viewed, the service endpoint will display a JSON status page that looks like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"OK": true,
|
||||
"Errors": [],
|
||||
"CheckDetails": {
|
||||
"kuberhealthy/daemonset": {
|
||||
"OK": true,
|
||||
"Errors": [],
|
||||
"RunDuration": "22.512278967s",
|
||||
"Namespace": "kuberhealthy",
|
||||
"LastRun": "2020-04-06T23:20:31.7176964Z",
|
||||
"AuthoritativePod": "kuberhealthy-67bf8c4686-mbl2j",
|
||||
"uuid": "9abd3ec0-b82f-44f0-b8a7-fa6709f759cd"
|
||||
},
|
||||
"kuberhealthy/deployment": {
|
||||
"OK": true,
|
||||
"Errors": [],
|
||||
"RunDuration": "29.142295647s",
|
||||
"Namespace": "kuberhealthy",
|
||||
"LastRun": "2020-04-06T23:20:31.7176964Z",
|
||||
"AuthoritativePod": "kuberhealthy-67bf8c4686-mbl2j",
|
||||
"uuid": "5f0d2765-60c9-47e8-b2c9-8bc6e61727b2"
|
||||
},
|
||||
"kuberhealthy/dns-status-internal": {
|
||||
"OK": true,
|
||||
"Errors": [],
|
||||
"RunDuration": "2.43940936s",
|
||||
"Namespace": "kuberhealthy",
|
||||
"LastRun": "2020-04-06T23:20:44.6294547Z",
|
||||
"AuthoritativePod": "kuberhealthy-67bf8c4686-mbl2j",
|
||||
"uuid": "c85f95cb-87e2-4ff5-b513-e02b3d25973a"
|
||||
}
|
||||
},
|
||||
"CurrentMaster": "kuberhealthy-7cf79bdc86-m78qr"
|
||||
}
|
||||
```
|
||||
|
||||
This JSON page displays all Kuberhealthy checks running in your cluster. If you have Kuberhealthy checks running in different namespaces, you can filter them by adding the `GET` variable `namespace` parameter: `?namespace=kuberhealthy,kube-system` onto the status page URL.
|
||||
|
||||
|
||||
### Writing Your Own Checks
|
||||
|
||||
Kuberhealthy is designed to be extended with custom check containers that can be written by anyone to check anything. These checks can be written in any language as long as they are packaged in a container. This makes Kuberhealthy an excellent platform for creating your own synthetic checks!
|
||||
|
||||
Creating your own check is a great way to validate your client library, simulate real user workflow, and create a high level of confidence in your service or system uptime.
|
||||
|
||||
To learn more about writing your own checks, along with simple examples, check the [custom check creation](https://github.com/Comcast/kuberhealthy/blob/master/docs/EXTERNAL_CHECK_CREATION.md) documentation.
|
||||
|
||||
|
||||
### Prometheus Integration Details
|
||||
|
||||
When enabling Prometheus (not the operator), the Kuberhealthy service gets the following annotations added:
|
||||
```.env
|
||||
prometheus.io/path: /metrics
|
||||
prometheus.io/port: "80"
|
||||
prometheus.io/scrape: "true"
|
||||
```
|
||||
|
||||
In your prometheus configuration, add the following example scrape_config that scrapes the Kuberhealthy service given the added prometheus annotation:
|
||||
|
||||
```yaml
|
||||
- job_name: 'kuberhealthy'
|
||||
scrape_interval: 1m
|
||||
honor_labels: true
|
||||
metrics_path: /metrics
|
||||
kubernetes_sd_configs:
|
||||
- role: service
|
||||
namespaces:
|
||||
names:
|
||||
- kuberhealthy
|
||||
relabel_configs:
|
||||
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
|
||||
action: keep
|
||||
regex: true
|
||||
```
|
||||
|
||||
You can also specify the target endpoint to be scraped using this example job:
|
||||
```yaml
|
||||
- job_name: kuberhealthy
|
||||
scrape_interval: 1m
|
||||
honor_labels: true
|
||||
metrics_path: /metrics
|
||||
static_configs:
|
||||
- targets:
|
||||
- kuberhealthy.kuberhealthy.svc.cluster.local:80
|
||||
```
|
||||
|
||||
Once the appropriate prometheus configurations are applied, you should be able to see the following Kuberhealthy metrics:
|
||||
- `kuberhealthy_check`
|
||||
- `kuberhealthy_check_duration_seconds`
|
||||
- `kuberhealthy_cluster_states`
|
||||
- `kuberhealthy_running`
|
||||
|
||||
### Creating Key Performance Indicators
|
||||
|
||||
Using these Kuberhealthy metrics, our team has been able to collect KPIs based on the following definitions, calculations, and PromQL queries.
|
||||
|
||||
*Availability*
|
||||
|
||||
We define availability as the K8s cluster control plane being up and functioning as expected. This is measured by our ability to create a deployment, do a rolling update, and delete the deployment within a set period of time.
|
||||
|
||||
We calculate this by measuring Kuberhealthy's [deployment check](https://github.com/Comcast/kuberhealthy/tree/master/cmd/deployment-check) successes and failures.
|
||||
- Availability = Uptime / (Uptime * Downtime)
|
||||
- Uptime = Number of Deployment Check Passes * Check Run Interval
|
||||
- Downtime = Number of Deployment Check Fails * Check Run Interval
|
||||
- Check Run Interval = how often the check runs (`runInterval` set in your KuberhealthyCheck Spec)
|
||||
|
||||
- PromQL Query (Availability % over the past 30 days):
|
||||
```promql
|
||||
1 - (sum(count_over_time(kuberhealthy_check{check="kuberhealthy/deployment", status="0"}[30d])) OR vector(0))/(sum(count_over_time(kuberhealthy_check{check="kuberhealthy/deployment", status="1"}[30d])) * 100)
|
||||
```
|
||||
|
||||
*Utilization*
|
||||
|
||||
We define utilization as user uptake of product (k8s) and its resources (pods, services, etc.). This is measured by how many nodes, deployments, statefulsets, persistent volumes, services, pods, and jobs are being utilized by our customers.
|
||||
We calculate this by counting the total number of nodes, deployments, statefulsets, persistent volumes, services, pods, and jobs.
|
||||
|
||||
*Duration (Latency)*
|
||||
|
||||
We define duration as the control plane's capacity and utilization of throughput. We calculate this by capturing the average run duration of a Kuberhealthy [deployment check](https://github.com/Comcast/kuberhealthy/tree/master/cmd/deployment-check) run.
|
||||
|
||||
- PromQL Query (Deployment check average run duration):
|
||||
```promql
|
||||
avg(kuberhealthy_check_duration_seconds{check="kuberhealthy/deployment"})
|
||||
```
|
||||
|
||||
*Errors / Alerts*
|
||||
|
||||
We define errors as all k8s cluster and Kuberhealthy related alerts. Every time one of our Kuberhealthy check fails, we are alerted of this failure.
|
||||
|
||||
### Thank You!
|
||||
|
||||
Thanks again to everyone in the community for all of your contributions and help! We are excited to see what you build. As always, if you find an issue, have a feature request, or need to open a pull request, please [open an issue](https://github.com/Comcast/kuberhealthy/issues) on the Github project.
|
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
layout: blog
|
||||
title: Supporting the Evolving Ingress Specification in Kubernetes 1.18
|
||||
date: 2020-06-05
|
||||
slug: Supporting-the-Evolving-Ingress-Specification-in-Kubernetes-1.18
|
||||
---
|
||||
|
||||
**Authors:** Alex Gervais (Datawire.io)
|
||||
|
||||
Earlier this year, the Kubernetes team released [Kubernetes 1.18](https://kubernetes.io/blog/2020/03/25/kubernetes-1-18-release-announcement/), which extended Ingress. In this blog post, we’ll walk through what’s new in the new Ingress specification, what it means for your applications, and how to upgrade to an ingress controller that supports this new specification.
|
||||
|
||||
### What is Kubernetes Ingress
|
||||
When deploying your applications in Kubernetes, one of the first challenges many people encounter is how to get traffic into their cluster. [Kubernetes ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) is a collection of routing rules that govern how external users access services running in a Kubernetes cluster. There are [three general approaches](https://blog.getambassador.io/kubernetes-ingress-nodeport-load-balancers-and-ingress-controllers-6e29f1c44f2d) for exposing your application:
|
||||
|
||||
* Using a `NodePort` to expose your application on a port across each of your nodes
|
||||
* Using a `LoadBalancer` service to create an external load balancer that points to a Kubernetes service in your cluster
|
||||
* Using a Kubernetes Ingress resource
|
||||
|
||||
### What’s new in Kubernetes 1.18 Ingress
|
||||
There are three significant additions to the Ingress API in Kubernetes 1.18:
|
||||
|
||||
* A new `pathType` field
|
||||
* A new `IngressClass` resource
|
||||
* Support for wildcards in hostnames
|
||||
|
||||
The new `pathType` field allows you to specify how Ingress paths should match.
|
||||
The field supports three types: `ImplementationSpecific` (default), `exact`, and `prefix`. Explicitly defining the expected behavior of path matching will allow every ingress-controller to support a user’s needs and will increase portability between ingress-controller implementation solutions.
|
||||
|
||||
The `IngressClass` resource specifies how Ingresses should be implemented by controllers. This was added to formalize the commonly used but never standardized `kubernetes.io/ingress.class` annotation and allow for implementation-specific extensions and configuration.
|
||||
|
||||
You can read more about these changes, as well as the support for wildcards in hostnames in more detail in [a previous blog post](https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/).
|
||||
|
||||
## Supporting Kubernetes ingress
|
||||
[Ambassador](https://www.getambassador.io) is an open-source Envoy-based ingress controller. We believe strongly in supporting common standards such as Kubernetes ingress, which we adopted and [announced our initial support for back in 2019](https://blog.getambassador.io/ambassador-ingress-controller-better-config-reporting-updated-envoy-proxy-99dc9139e28f).
|
||||
|
||||
Every Ambassador release goes through rigorous testing. Therefore, we also contributed an [open conformance test suite](https://github.com/kubernetes-sigs/ingress-controller-conformance), supporting Kubernetes ingress. We wrote the initial bits of test code and will keep iterating over the newly added features and different versions of the Ingress specification as it evolves to a stable v1 GA release. Documentation and usage samples, is one of our top priorities. We understand how complex usage can be, especially when transitioning from a previous version of an API.
|
||||
|
||||
Following a test-driven development approach, the first step we took in supporting Ingress improvements in Ambassador was to translate the revised specification -- both in terms of API and behavior -- into a comprehensible test suite. The test suite, although still under heavy development and going through multiple iterations, was rapidly added to the Ambassador CI infrastructure and acceptance criteria. This means every change to the Ambassador codebase going forward will be compliant with the Ingress API and be tested end-to-end in a lightweight [KIND cluster](https://kind.sigs.k8s.io/). Using KIND allowed us to make rapid improvements while limiting our cloud provider infrastructure bill and testing out unreleased Kubernetes features with pre-release builds.
|
||||
|
||||
### Adopting a new specification
|
||||
With a global comprehension of additions to Ingress introduced in Kubernetes 1.18 and a test suite on hand, we tackled the task of adapting the Ambassador code so that it would support translating the high-level Ingress API resources into Envoy configurations and constructs. Luckily Ambassador already supported previous versions of ingress functionalities so the development effort was incremental.
|
||||
|
||||
We settled on a controller name of `getambassador.io/ingress-controller`. This value, consistent with Ambassador's domain and CRD versions, must be used to tie in an IngressClass `spec.controller` with an Ambassador deployment. The new IngressClass resource allows for extensibility by setting a `spec.parameters` field. At the moment Ambassador makes no use of this field and its usage is reserved for future development.
|
||||
|
||||
Paths can now define different matching behaviors using the `pathType` field. The field will default to a value of `ImplementationSpecific`, which uses the same matching rules as the [Ambassador Mappings](https://www.getambassador.io/docs/latest/topics/using/mappings/) prefix field and previous Ingress specification for backward compatibility reasons.
|
||||
|
||||
### Kubernetes Ingress Controllers
|
||||
A comprehensive [list of Kubernetes ingress controllers](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/) is available in the Kubernetes documentation. Currently, Ambassador is the only ingress controller that supports these new additions to the ingress specification. Powered by the [Envoy Proxy](https://www.envoyproxy.io), Ambassador is the fastest way for you to try out the new ingress specification today.
|
||||
|
||||
Check out the following resources:
|
||||
|
||||
* Ambassador on [GitHub](https://www.github.com/datawire/ambassador)
|
||||
* The Ambassador [documentation](https://www.getambassador.io/docs)
|
||||
* [Improvements to the Ingress API](https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/)
|
||||
|
||||
Or join the community on [Slack](http://d6e.co/slack)!
|
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 224 KiB |
|
@ -0,0 +1,109 @@
|
|||
---
|
||||
title: Babylon Case Study
|
||||
linkTitle: Babylon
|
||||
case_study_styles: true
|
||||
cid: caseStudies
|
||||
css: /css/case-studies-gradient.css
|
||||
logo: babylon_featured_logo.svg
|
||||
featured: true
|
||||
weight: 1
|
||||
quote: >
|
||||
Kubernetes is a great platform for machine learning because it comes with all the scheduling and scalability that you need.
|
||||
---
|
||||
|
||||
|
||||
<div class="article image overlay" style="background-image: url('/images/babylon4.jpg')">
|
||||
<h1> CASE STUDY: Babylon</h1>
|
||||
<div class="subhead">How Cloud Native Is Enabling Babylon’s Medical AI Innovations</div>
|
||||
</div>
|
||||
|
||||
<div class="details">
|
||||
Company <b>Babylon</b> Location <b>United Kingdom</b> Industry <b>AI, Healthcare</b>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<section class="section1">
|
||||
<div class="colsgradient">
|
||||
<div class="col1">
|
||||
<h2>Challenge</h2>
|
||||
A large number of Babylon’s products leverage machine learning and artificial intelligence, and in 2019, there wasn’t enough computing power in-house to run a particular experiment. The company was also growing (from 100 to 1,600 in three years) and planning expansion into other countries.
|
||||
|
||||
|
||||
<h2>Solution</h2>
|
||||
Babylon had migrated its user-facing applications to a Kubernetes platform in 2018, so the infrastructure team turned to Kubeflow, a toolkit for machine learning on Kubernetes. “We tried to create a Kubernetes core server, we deployed Kubeflow, and we orchestrated the whole experiment, which ended up being a really good success,” says AI Infrastructure Lead Jérémie Vallée. The team began building a self-service AI training platform on top of Kubernetes.
|
||||
|
||||
<h2>Impact</h2>
|
||||
Instead of waiting hours or days to be able to compute, teams can get access instantaneously. Clinical validations used to take 10 hours; now they are done in under 20 minutes. The portability of the cloud native platform has also enabled Babylon to expand into other countries.</div>
|
||||
</div>
|
||||
</section>
|
||||
<div class="article image overlay" style="background-image: url('/images/babylon1.jpg');">
|
||||
<div class="quotetext">
|
||||
“Kubernetes is a great platform for machine learning because it comes with all the scheduling and scalability that you need.”
|
||||
<p><div class="quoteauthortext">- JÉRÉMIE VALLÉE, AI INFRASTRUCTURE LEAD AT BABYLON</div></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<section class="section2">
|
||||
<div class="fullcol">
|
||||
<h4>Babylon’s mission is to put accessible and affordable healthcare services in the hands of every person on earth.</h4>
|
||||
|
||||
<p>Since its launch in the U.K. in 2013, the startup has facilitated millions of digital consultations around the world. In the U.K., patients were typically waiting a week or two for a doctor’s appointment. Through Babylon’s NHS service, GP at Hand—which has more than 75,000 registered patients—39% get an appointment through their phone within 30 minutes, and 89% within 6 hours. </p>
|
||||
|
||||
<p>That’s just the start. “We try to combine different types of technology with the medical expertise that we have in-house to build products that will help patients manage and understand their health, and also help doctors be more efficient at what they do,” says Jérémie Vallée, AI Infrastructure Lead at Babylon. </p>
|
||||
|
||||
<p>A large number of these products leverage machine learning and artificial intelligence, and in 2019, researchers hit a pain point. “We have some servers in-house where our researchers were doing a lot of AI experiments and some training of models, and we came to a point where we didn’t have enough compute in-house to run a particular experiment,” says Vallée. </p>
|
||||
<p>
|
||||
Babylon had migrated its user-facing applications to a Kubernetes platform in 2018, “and we had a lot of Kubernetes knowledge thanks to the migration,” he adds. To optimize some of the models that had been created, the team turned to Kubeflow, a toolkit for machine learning on Kubernetes. “We tried to create a Kubernetes core server, we deployed Kubeflow, and we orchestrated the whole experiment, which ended up being a really good success,” he says.</p>
|
||||
<p>
|
||||
Based on that experience, Vallée’s team was tasked with building a self-service platform to help Babylon’s AI teams become more efficient, and by extension help get products to market faster. The main requirements: (1) the ability to give researchers and engineers access to the compute they needed, regardless of the size of the experiments they may need to run; (2) a way to provide teams with the best tools that they needed to do their work, on demand and in a centralized way; and (3) the training platform had to be close to the data that was being managed, because of the company’s expansion into different countries.</p>
|
||||
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="greybanner">
|
||||
<div class="greyquotetext">
|
||||
“Delivering a self-service platform where users are empowered to run their own workload has enabled our data scientist community to do hyper parameter tuning and general algorithm development without any cloud skill and without the help of platform engineers, thus accelerating our innovation.”<p><div class="quoteauthortext">- CAROLINE HARGROVE, CHIEF TECHNOLOGY OFFICER AT BABYLON</div></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="section3">
|
||||
<div class="fullcol">
|
||||
<p>
|
||||
Kubernetes was an enabler on every count. “Kubernetes is a great platform for machine learning because it comes with all the scheduling and scalability that you need,” says Vallée. The need to keep data in every country in which Babylon operates requires a multi-region, multi-cloud strategy, and some countries might not even have a public cloud provider at all. “We wanted to make this platform portable so that we can run training jobs anywhere,” he says. “Kubernetes offered a base layer that allows you to deploy the platform outside of the cloud provider, and then deploy whatever tooling you need. That was a very good selling point for us.” </p>
|
||||
<p>
|
||||
Once the team decided to build the Babylon AI Research platform on top of Kubernetes, they referred to the Cloud Native Landscape to build out the stack: Prometheus and Grafana for monitoring; an Istio service mesh to control the network on the training platform and control what access all of the workflows would have; Helm to deploy the stack; and Flux to manage the GitOps part of the pipeline. </p>
|
||||
<p>
|
||||
The cloud native AI platform has had a huge impact at Babylon. The first research projects run on the platform mostly involved machine learning and natural language processing. These experiments required a huge amount of compute—1600 CPU, 3.2 TB RAM—which was much more than Babylon had in-house. Plus, access to compute used to take hours, or sometimes even days, depending on how busy the platform team was. “Now, with Kubernetes and the self-service platform that we provide, it’s pretty much instantaneous,” says Vallée. </p>
|
||||
<p>
|
||||
Another important type of work that’s done on the platform is clinical validation for new applications such as Babylon’s Symptom Checker, which calculates the probability of a disease given the evidence input by the user. “Being in healthcare, we want all of our models to be safe before they’re going to hit production,” says Vallée. Using Argo for GitOps “enabled us to scale the process massively.” </p>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<div class="article image overlay" style="background-image: url('/images/babylon2.jpg');">
|
||||
<div class="quotetext">
|
||||
“Giving a Kubernetes-based platform to our data scientists has meant increased security, increased innovation through empowerment, and a more affordable health service as our cloud engineers are building an experience that is used by hundreds on a daily basis, rather than supporting specific bespoke use cases.” <p><div class="quoteauthortext">- JEAN MARIE FERDEGUE, DIRECTOR OF PLATFORM OPERATIONS AT BABYLON</div></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="section5">
|
||||
<div class="fullcol">
|
||||
<p>
|
||||
Researchers used to have to wait up to 10 hours to get results on new versions of their models. With Kubernetes, that time is now down to under 20 minutes. Plus, previously they could only run one clinical validation at a time, now they can run many parallel ones if they need to—a huge benefit considering that in the past three years, Babylon has grown from 100 to 1,600 employees. </p>
|
||||
<p>
|
||||
“Delivering a self-service platform where users are empowered to run their own workload has enabled our data scientist community to do hyper parameter tuning and general algorithm development without any cloud skill and without the help of platform engineers, thus accelerating our innovation,” says Chief Technology Officer Caroline Hargrove.</p>
|
||||
<p>
|
||||
Adds Director of Platform Operations Jean Marie Ferdegue: “Giving a Kubernetes-based platform to our data scientists has meant increased security, increased innovation through empowerment, and a more affordable health service as our cloud engineers are building an experience that is used by hundreds on a daily basis, rather than supporting specific bespoke use cases.” </p>
|
||||
<p>
|
||||
Plus, as Babylon continues to expand, “it will be very easy to onboard new countries,” says Vallée. “Fifteen months ago when we deployed this platform, we had one big environment in the U.K., but now we have one in Canada, we have one in Asia, and we have one coming in the U.S. This is one of the things that Kubernetes and the other cloud native projects have enabled for us.”
|
||||
</p>
|
||||
<p>
|
||||
Babylon’s road map for cloud native involves onboarding all of the company’s AI efforts to the platform. Increasingly, that includes AI services of care. “I think this is going to be an interesting field where AI and healthcare meet,” Vallée says. “It’s kind of a complex problem and there’s a lot of issues around this. So with our platform, we want to say, ‘What can we do to make this less painful for our developers and machine learning engineers?’”
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 9.2 KiB |
|
@ -0,0 +1,117 @@
|
|||
---
|
||||
title: Booking.com Case Study
|
||||
linkTitle: Booking.com
|
||||
case_study_styles: true
|
||||
cid: caseStudies
|
||||
css: /css/case-studies-gradient.css
|
||||
logo: booking.com_featured_logo.png
|
||||
featured: true
|
||||
weight: 3
|
||||
quote: >
|
||||
We realized that we needed to learn Kubernetes better in order to fully use the potential of it. At that point, we made the shift to build our own Kubernetes platform.
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="article image overlay" style="background-image: url('/images/booking1.jpg')">
|
||||
<h1> CASE STUDY: Booking.com</h1>
|
||||
<div class="subhead">After Learning the Ropes with a Kubernetes Distribution, Booking.com Built a Platform of Its Own</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="details">
|
||||
Company <b>Booking.com</b> Location <b>Netherlands</b> Industry <b>Travel</b>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<section class="section1">
|
||||
<div class="colsgradient">
|
||||
<div class="col1">
|
||||
<h2>Challenge</h2>
|
||||
In 2016, Booking.com migrated to an OpenShift platform, which gave product developers faster access to infrastructure. But because Kubernetes was abstracted away from the developers, the infrastructure team became a “knowledge bottleneck” when challenges arose. Trying to scale that support wasn’t sustainable.
|
||||
|
||||
|
||||
<h2>Solution</h2>
|
||||
After a year operating OpenShift, the platform team decided to build its own vanilla Kubernetes platform—and ask developers to learn some Kubernetes in order to use it. “This is not a magical platform,” says Ben Tyler, Principal Developer, B Platform Track. “We’re not claiming that you can just use it with your eyes closed. Developers need to do some learning, and we’re going to do everything we can to make sure they have access to that knowledge.”
|
||||
|
||||
<h2>Impact</h2>
|
||||
Despite the learning curve, there’s been a great uptick in adoption of the new Kubernetes platform. Before containers, creating a new service could take a couple of days if the developers understood Puppet, or weeks if they didn’t. On the new platform, it can take as few as 10 minutes. About 500 new services were built on the platform in the first 8 months.
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div class="article image overlay" style="background-image: url('/images/booking2.JPG');">
|
||||
<div class="quotetext">
|
||||
“As our users learn Kubernetes and become more sophisticated Kubernetes users, they put pressure on us to provide a better, more native Kubernetes experience, which is great. It’s a super healthy dynamic.”
|
||||
<p><div class="quoteauthortext">- BEN TYLER, PRINCIPAL DEVELOPER, B PLATFORM TRACK AT BOOKING.COM</div></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<section class="section2">
|
||||
<div class="fullcol">
|
||||
<h4>Booking.com has a long history with Kubernetes: In 2015, a team at the travel platform prototyped a container platform based on Mesos and Marathon.
|
||||
</h4>
|
||||
|
||||
<p>Impressed by what the technology offered, but in need of enterprise features at its scale—the site handles more than 1.5 million room-night reservations a day on average—the team decided to adopt an OpenShift platform.</p>
|
||||
|
||||
<p>This platform, which was wrapped in a Heroku-style, high-level CLI interface, “was definitely popular with our product developers,” says Ben Tyler, Principal Developer, B Platform Track. “We gave them faster access to infrastructure.”</p>
|
||||
|
||||
<p>But, he adds, “anytime something went slightly off the rails, developers didn’t have any of the knowledge required to support themselves.”</p>
|
||||
|
||||
<p>And after a year of operating this platform, the infrastructure team found that it had become “a knowledge bottleneck,” he says. “Most of the developers who used it did not know it was Kubernetes underneath. An application failure and a platform failure both looked like failures of that Heroku-style tool.”</p>
|
||||
<p>
|
||||
Scaling the necessary support did not seem feasible or sustainable, so the platform team needed a new solution. The understanding of Kubernetes that they had gained operating the OpenShift platform gave them confidence to build a vanilla Kubernetes platform of their own and customize it to suit the company’s needs.</p>
|
||||
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="greybanner">
|
||||
<div class="greyquotetext">
|
||||
“For entering the landscape, OpenShift was definitely very helpful. It shows you what the technology can do, and it makes it easy for you to use it. After we spent some time on it, we realized that we needed to learn Kubernetes better in order to fully use the potential of it. At that point, we made the shift to build our own Kubernetes platform. We definitely benefit in the long term for taking that step and investing the time in gaining that knowledge.”<p><div class="quoteauthortext">- EDUARD IACOBOAIA, SENIOR SYSTEM ADMINISTRATOR, B PLATFORM TRACK AT BOOKING.COM</div></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="section3">
|
||||
<div class="fullcol">
|
||||
<p>
|
||||
“For entering the landscape, OpenShift was definitely very helpful,” says Eduard Iacoboaia, Senior System Administrator, B Platform Track. “It shows you what the technology can do, and it makes it easy for you to use it. After we spent some time on it, we realized that we needed to learn Kubernetes better in order to fully use the potential of it. At that point, we made the shift to build our own Kubernetes platform. We definitely benefit in the long term for taking that step and investing the time in gaining that knowledge.” </p>
|
||||
<p>
|
||||
Iacoboaia’s team had customized a lot of OpenShift tools to make them work at Booking.com, and “those integrations points were kind of fragile,” he says. “We spent much more time understanding all the components of Kubernetes, how they work, how they interact with each other.” That research led the team to switch from OpenShift’s built-in Ansible playbooks to Puppet deployments, which are used for the rest of Booking’s infrastructure. The control plane was also moved from inside the cluster onto bare metal, as the company runs tens of thousands of bare-metal servers and a large infrastructure for running applications on bare metal. (Booking runs Kubernetes in multiple clusters in multiple data centers across the various regions where it has compute.) “We decided to keep it as simple as possible and to also use the tools that we know best,” says Iacoboaia. </p>
|
||||
<p>
|
||||
The other big change was that product engineers would have to learn Kubernetes in order to onboard. “This is not a magical platform,” says Tyler. “We’re not claiming that you can just use it with your eyes closed. Developers need to do some learning, and we’re going to do everything we can to make sure they have access to that knowledge.” That includes trainings, blog posts, videos, and Udemy courses. </p>
|
||||
<p>
|
||||
Despite the learning curve, there’s been a great uptick in adoption of the new Kubernetes platform. “I think the reason we’ve been able to strike this bargain successfully is that we’re not asking them to learn a proprietary app system,” says Tyler. “We’re asking them to learn something that’s open source, where the knowledge is transferable. They’re investing in their own careers by learning Kubernetes.”</p>
|
||||
<p>
|
||||
One clear sign that this strategy has been a success is that in the support channel, when users have questions, other product engineers are jumping in to respond. “I haven’t seen that kind of community engagement around a particular platform product internally before,” says Tyler. “It helps a lot that it’s visibly an ecosystem standard outside of the company, so people feel value in investing in that knowledge and sharing it with others, which is really, really powerful.” </p>
|
||||
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<div class="article image overlay" style="background-image: url('/images/booking3.jpg');">
|
||||
<div class="quotetext">
|
||||
“We have a tutorial. You follow the tutorial. Your code is running. Then, it’s business-logic time. The time to gain access to resources is decreased enormously.” <p><div class="quoteauthortext">- BEN TYLER, PRINCIPAL DEVELOPER, B PLATFORM TRACK AT BOOKING.COM</div></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="section5">
|
||||
<div class="fullcol">
|
||||
<p>
|
||||
There’s other quantifiable evidence too: Before containers, creating a new service could take a couple of days if the developers understood Puppet, or weeks if they didn’t. On the new platform, it takes 10 minutes. “We have a tutorial. You follow the tutorial. Your code is running. Then, it’s business-logic time,” says Tyler. “The time to gain access to resources is decreased enormously.” About 500 new services were built in the first 8 months on the platform, with hundreds of releases per day. </p>
|
||||
<p>
|
||||
The platform offers different “layers of contracts, so to speak,” says Tyler. “At the very base, it’s just Kubernetes. If you’re a pro Kubernetes user, here’s a Kubernetes API, just like you get from GKE or AKS. We’re trying to be a provider on that same level. But our whole job inside the company is to be a bigger value add than just vanilla infrastructure, so we provide a set of base images for our main stacks, Perl and Java.”
|
||||
</p>
|
||||
<p>
|
||||
And “as our users learn Kubernetes and become more sophisticated Kubernetes users, they put pressure on us to provide a better more native Kubernetes experience, which is great,” says Tyler. “It’s a super healthy dynamic.”</p>
|
||||
<p>
|
||||
The platform also includes other CNCF technologies, such as Envoy, Helm, and Prometheus. Most of the critical service traffic for Booking.com is routed through Envoy, and Prometheus is used primarily to monitor infrastructure components. Helm is consumed as a packaging standard. The team also developed and open sourced Shipper, an extension for Kubernetes to add more complex rollout strategies and multi-cluster orchestration.
|
||||
</p>
|
||||
<p>
|
||||
To be sure, there have been internal discussions about the wisdom of building a Kubernetes platform from the ground up. “This is not really our core competency—Kubernetes and travel, they’re kind of far apart, right?” says Tyler. “But we’ve made a couple of bets on CNCF components that have worked out really well for us. Envoy and Kubernetes, in particular, have been really beneficial to our organization. We were able to customize them, either because we could look at the source code or because they had extension points, and we were able to get value out of them very quickly without having to change any paradigms internally.”
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 1.9 KiB |
|
@ -0,0 +1,103 @@
|
|||
---
|
||||
title: Booz Allen Case Study
|
||||
linkTitle: Booz Allen Hamilton
|
||||
case_study_styles: true
|
||||
cid: caseStudies
|
||||
css: /css/case-studies-gradient.css
|
||||
logo: booz-allen-featured-logo.svg
|
||||
featured: true
|
||||
weight: 2
|
||||
quote: >
|
||||
Kubernetes is a great solution for us. It allows us to rapidly iterate on our clients’ demands.
|
||||
---
|
||||
|
||||
|
||||
|
||||
<div class="article image overlay" style="background-image: url('/images/BoozAllen4.jpg')">
|
||||
<h1> CASE STUDY: Booz Allen Hamilton</h1>
|
||||
<div class="subhead">How Booz Allen Hamilton Is Helping Modernize the Federal Government with Kubernetes</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="details">
|
||||
Company <b>Booz Allen Hamilton</b> Location <b>United States</b> Industry <b>Government</b>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<section class="section1">
|
||||
<div class="colsgradient">
|
||||
<div class="col1">
|
||||
<h2>Challenge</h2>
|
||||
In 2017, Booz Allen Hamilton’s Strategic Innovation Group worked with the federal government to relaunch the decade-old recreation.gov website, which provides information and real-time booking for more than 100,000 campsites and facilities on federal lands across the country. The infrastructure needed to be agile, reliable, and scalable—as well as repeatable for the other federal agencies that are among Booz Allen Hamilton’s customers.
|
||||
|
||||
<h2>Solution</h2>
|
||||
“The only way that we thought we could be successful with this problem across all the different agencies is to create a microservice architecture and containers, so that we could be very dynamic and very agile to any given agency for whatever requirements that they may have,” says Booz Allen Hamilton Senior Lead Technologist Martin Folkoff. To meet those requirements, Folkoff’s team looked to Kubernetes for orchestration.
|
||||
|
||||
<h2>Impact</h2>
|
||||
With the recreation.gov Kubernetes platform, changes can be implemented in about 30 minutes, compared to the multiple hours or even days legacy government applications require to review the code, get approval, and deploy the fix. Recreation.gov deploys to production on average 10 times a day. With monitoring, security, and logging built in, developers can create and publish new services to production within a week. Additionally, Folkoff says, “supporting the large, existing monoliths in the government is extremely expensive,” and migrating into a more modern platform has resulted in perhaps 50% cost savings.
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div class="article image overlay" style="background-image: url('/images/BoozAllen2.jpg');">
|
||||
<div class="quotetext">
|
||||
"When there’s a regulatory change in an agency, or a legislative change in Congress, or an executive order that changes the way you do business, how do I deploy that and get that out to the people who need it rapidly? At the end of the day, that’s the problem we’re trying to help the government solve with tools like Kubernetes."
|
||||
<p><div class="quoteauthortext">- JOSH BOYD, CHIEF TECHNOLOGIST AT BOOZ ALLEN HAMILTON</div></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<section class="section2">
|
||||
<div class="fullcol">
|
||||
<h4>The White House launched an IT modernization effort in 2017, and in addition to improving cybersecurity and shifting to the public cloud and a consolidated IT model, “the federal government is looking to provide a better experience to citizens in every way that we interact with the government through every channel,” says Booz Allen Hamilton Senior Lead Technologist Martin Folkoff.</h4>
|
||||
|
||||
<p>To that end, Folkoff’s Strategic Innovation Group worked with the federal government last year to relaunch the decade-old recreation.gov website, which provides information and real-time booking for more than 100,000 campsites and facilities on federal lands across the country.</p>
|
||||
|
||||
<p>The infrastructure needed to be agile, reliable, and scalable—as well as repeatable for the other federal agencies that are among Booz Allen Hamilton’s customers. “The only way that we thought we could be successful with this problem across all the different agencies is to create a microservice architecture, so that we could be very dynamic and very agile to any given agency for whatever requirements that they may have,” says Folkoff.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="greybanner">
|
||||
<div class="greyquotetext">
|
||||
"With CNCF, there’s a lot of focus on scale, and so there’s a lot of comfort knowing that as the project grows, we’re going to be comfortable using that tool set."<p><div class="quoteauthortext">- MARTIN FOLKOFF, SENIOR LEAD TECHNOLOGIST AT BOOZ ALLEN HAMILTON</div></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="section3">
|
||||
<div class="fullcol">
|
||||
<p>
|
||||
Booz Allen Hamilton, which has provided consulting services to the federal government for more than a century, introduced microservices, Docker containers, and AWS to its federal agency clients about five years ago. The next logical step was Kubernetes for orchestration. “Knowing that we had to be really agile and really reliable and scalable, we felt that the only technology that we know that can enable those kinds of things are the ones the CNCF provides,” Folkoff says. “One of the things that is always important for the government is to make sure that the things that we build really endure. Using technology that is supported across multiple different companies and has strong governance gives people a lot of confidence.”</p>
|
||||
<p>
|
||||
Kubernetes was also aligned with the government’s open source and IT modernization initiatives, so there has been an uptick in its usage at federal agencies over the past two years. “Now that Kubernetes is becoming offered as a service by the cloud providers like AWS and Microsoft, we’re starting to see even more interest,” says Chief Technologist Josh Boyd. Adds Folkoff: “With CNCF, there’s a lot of focus on scale, and so there’s a lot of comfort knowing that as the project grows, we’re going to be comfortable using that tool set.” </p>
|
||||
<p>
|
||||
The greenfield recreation.gov project allowed the team to build a new Kubernetes-enabled site running on AWS, and the migration lasted only a week, when the old site didn’t take bookings. “For the actual transition, we just swapped a DNS server, and it only took about 35 seconds between the old site being down and our new site being up and available,” Folkoff adds. </p>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<div class="article image overlay" style="background-image: url('/images/BoozAllen1.png');">
|
||||
<div class="quotetext">
|
||||
"Kubernetes alone enables a dramatic reduction in cost as resources are prioritized to the day’s event" <p><div class="quoteauthortext">- MARTIN FOLKOFF, SENIOR LEAD TECHNOLOGIST AT BOOZ ALLEN HAMILTON</div></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="section5">
|
||||
<div class="fullcol">
|
||||
<p>
|
||||
In addition to its work with the Department of Interior for recreation.gov, Booz Allen Hamilton has brought Kubernetes to various Defense, Intelligence, and civilian agencies. Says Boyd: “When there’s a regulatory change in an agency, or a legislative change in Congress, or an executive order that changes the way you do business, how do I deploy that and get that out to the people who need it rapidly? At the end of the day, that’s the problem we’re trying to help the government solve with tools like Kubernetes.”</p>
|
||||
<p>
|
||||
For recreation.gov, the impact was clear and immediate. With the Kubernetes platform, Folkoff says, “if a new requirement for a permit comes out, we have the ability to design and develop and implement that completely independently of reserving a campsite. It provides a much better experience to users.” Today, changes can be implemented in about 30 minutes, compared to the multiple hours or even days legacy government applications require to review the code, get approval, and deploy the fix. Recreation.gov deploys to production on average 10 times a day. </p>
|
||||
<p>
|
||||
Developer velocity has been improved. “When I want to do monitoring or security or logging, I don’t have to do anything to my services or my application to enable that anymore,” says Boyd. “I get all of this magic just by being on the Kubernetes platform.” With all of those things built in, developers can create and publish new services to production within one week. </p>
|
||||
<p>
|
||||
Additionally, Folkoff says, “supporting the large, existing monoliths in the government is extremely expensive,” and migrating into a more modern platform has resulted in perhaps 50% cost savings. “Kubernetes alone enables a dramatic reduction in cost as resources are prioritized to the day’s event,” he says. “For example, during a popular campsite release, camping-related services are scaled out while permit services are scaled down.”</p>
|
||||
<p>
|
||||
So far, “Kubernetes is a great solution for us,” says Folkoff. “It allows us to rapidly iterate on our clients’ demands.” Looking ahead, the team sees further adoption of the Kubernetes platform across federal agencies. Says Boyd: “You get the ability for the rapid delivery of business value for your customers. You now have observability into everything that you’re doing. You don’t have these onesies and twosies unicorn servers anymore. Now everything that you deploy is deployed in the same way, it’s all instrumented the same way, and it’s all built and deployed the same way through our CI/CD processes.”</p>
|
||||
<p>
|
||||
They also see a push toward re-platforming. “There’s still a lot of legacy workloads out there,” says Boyd. “We’ve got the new challenges of greenfield development and integration with legacy systems, but also that brown field of ‘Hey, how do I take this legacy monolith and get it onto a platform where now it’s instrumented with all the magic of the Kubernetes platform without having to do a whole lot to my application?’ I think re-platforming is a pretty big use case for the government right now.”</p>
|
||||
<p>
|
||||
And given the success that they’ve had with Kubernetes so far, Boyd says, “I think at this point that technology is becoming pretty easy to sell.” Adds Folkoff: “People are really excited about being able to deploy, scale, be reliable, and do cheaper maintenance of all of this.”
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
|
@ -1 +0,0 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 215 127"><defs><style>.cls-1{fill:#fbfbfb;}.cls-2{fill:#918f90;}.cls-3{fill:#231f20;}.cls-4{fill:#fff;}</style></defs><title>kubernetes.io-logos</title><rect class="cls-1" x="-3.55202" y="-3.16104" width="223.25536" height="134.51136"/><g id="g10"><g id="g12"><path id="path14" class="cls-2" d="M58.27642,43.45186A13.87083,13.87083,0,1,1,44.40989,29.577,13.86679,13.86679,0,0,1,58.27642,43.45186"/><path id="path16" class="cls-2" d="M118.31862,43.45186A13.87534,13.87534,0,1,1,104.44607,29.577a13.868,13.868,0,0,1,13.87255,13.87483"/><path id="path18" class="cls-2" d="M58.27642,78.10812A13.87083,13.87083,0,1,1,44.40989,64.23586,13.86592,13.86592,0,0,1,58.27642,78.10812"/><path id="path20" class="cls-2" d="M88.30182,60.78355A13.87432,13.87432,0,1,1,74.42662,46.9099a13.876,13.876,0,0,1,13.8752,13.87365"/><path id="path22" class="cls-2" d="M88.30182,26.12046a13.87432,13.87432,0,1,1-13.8752-13.874,13.8772,13.8772,0,0,1,13.8752,13.874"/><path id="path24" class="cls-2" d="M88.30182,95.44422a13.87432,13.87432,0,1,1-13.8752-13.87233,13.88079,13.88079,0,0,1,13.8752,13.87233"/><path id="path26" class="cls-3" d="M104.405,91.88866a13.87443,13.87443,0,0,1,0-27.74885h57.96422a13.87443,13.87443,0,1,1,0,27.74885H104.405"/><path id="path28" class="cls-4" d="M108.44973,74.99434a3.07749,3.07749,0,0,0-2.90728-1.56908c-2.38678,0-3.75361,1.90181-3.75361,4.58681,0,2.60465,1.39092,4.5882,3.77637,4.5882a3.36511,3.36511,0,0,0,3.11217-1.83873l2.67963,1.44431a6.15354,6.15354,0,0,1-5.888,3.26586c-4.15781,0-6.95236-2.89435-6.95236-7.45964,0-4.40183,2.91073-7.45392,7.06838-7.45392a6.0724,6.0724,0,0,1,5.819,3.19984l-2.95428,1.23635"/><path id="path30" class="cls-4" d="M124.883,74.99434a3.07653,3.07653,0,0,0-2.91095-1.56908c-2.38369,0-3.74223,1.90181-3.74223,4.58681,0,2.60465,1.38424,4.5882,3.77234,4.5882a3.36145,3.36145,0,0,0,3.11217-1.83873l2.67889,1.44431a6.148,6.148,0,0,1-5.88579,3.26586c-4.15787,0-6.95353-2.89435-6.95353-7.45964,0-4.40183,2.90728-7.45392,7.06662-7.45392a6.08392,6.08392,0,0,1,5.82338,3.19984L124.883,74.99434"/><path id="path32" class="cls-4" d="M139.27909,78.98589h-2.91462v-5.41h2.91462a2.705,2.705,0,1,1,0,5.41Zm.78061-8.22983-6.88083.02438v14.466h3.1856v-3.448l3.69523-.02152a5.51047,5.51047,0,1,0,0-11.02093"/><path id="path34" class="cls-3" d="M178.45064,88.67875a2.45448,2.45448,0,1,0,2.45419-2.49252A2.4339,2.4339,0,0,0,178.45064,88.67875Zm5.36147,0a2.90728,2.90728,0,1,1-2.90728-2.90786,2.86847,2.86847,0,0,1,2.90728,2.90786"/><path id="path36" class="cls-3" d="M180.77632,88.4782h-.5302V87.34657h.73581c.398,0,.77694.105.77694.56112C181.75887,88.46212,181.27054,88.4782,180.77632,88.4782Zm.564.34309a.88252.88252,0,0,0,.82026-.9136c0-.5852-.32458-.90332-1.0626-.90332h-1.25647v3.26726h.40463V88.82129h.6778l.91794,1.45034h.47145l-.973-1.45034"/></g></g></svg>
|
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 20 KiB |
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: CCP Games
|
||||
content_url: https://cloud.google.com/customers/ccp-games/
|
||||
---
|
|
@ -5,11 +5,7 @@ linkTitle: chinaunicom
|
|||
case_study_styles: true
|
||||
cid: caseStudies
|
||||
css: /css/style_case_studies.css
|
||||
logo: chinaunicom_featured_logo.png
|
||||
featured: true
|
||||
weight: 1
|
||||
quote: >
|
||||
Kubernetes has improved our experience using cloud infrastructure. There is currently no alternative technology that can replace it.
|
||||
featured: false
|
||||
---
|
||||
|
||||
<div class="banner1" style="background-image: url('/images/CaseStudy_chinaunicom_banner1.jpg')">
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 215 127"><defs><style>.cls-1{fill:#fbfbfb;}.cls-2{fill:#2d2a26;}.cls-3{fill:#7d77b7;}.cls-4{fill:#ce1141;}.cls-5{fill:#009ddd;}.cls-6{fill:#f47a3f;}.cls-7{fill:#62bb46;}.cls-8{fill:#febe10;}</style></defs><title>kubernetes.io-logos</title><rect class="cls-1" x="-3.55202" y="-3.16104" width="223.25536" height="134.51136"/><path class="cls-2" d="M55.45758,63.38456a13.5171,13.5171,0,1,0,13.51376,13.515A13.52915,13.52915,0,0,0,55.45758,63.38456Zm0,24.37138a10.85428,10.85428,0,1,1,10.857-10.85638A10.87113,10.87113,0,0,1,55.45758,87.75594Z"/><path class="cls-2" d="M171.99062,77.07207c-.72693-.38066-5.1347-2.65285-5.77024-2.98164-2.31351-1.17937-3.134-2.227-3.134-3.99876,0-2.45829,2.01913-4.04731,5.151-4.04731a10.02931,10.02931,0,0,1,4.65811,1.395,1.35062,1.35062,0,0,0,.64672.16139,1.32785,1.32785,0,0,0,.66238-2.47883,12.80669,12.80669,0,0,0-5.96721-1.73741c-4.599,0-7.81231,2.75934-7.81231,6.70711,0,3.54721,2.33072,5.22038,4.61289,6.3856.63763.32484,5.09881,2.62542,5.76844,2.97772a4.46184,4.46184,0,0,1,2.73581,3.89862c0,2.13465-1.8074,4.40384-5.15493,4.40384a10.0211,10.0211,0,0,1-6.48209-2.855l-.20571-.19969-1.96907,1.79233.23225.22922a12.61506,12.61506,0,0,0,8.42462,3.69442c4.88887,0,7.81111-3.59336,7.81111-7.06515A7.12542,7.12542,0,0,0,171.99062,77.07207Z"/><path class="cls-2" d="M27.74831,66.04738a10.7845,10.7845,0,0,1,7.67687,3.1762,1.39844,1.39844,0,0,0,1.88011,0,1.32506,1.32506,0,0,0,0-1.87767l-.16108-.16741a13.5269,13.5269,0,1,0,.55047,18.86116L35.8143,84.15594a10.85243,10.85243,0,1,1-8.066-18.10856Z"/><path class="cls-2" d="M119.36676,66.04738a10.78435,10.78435,0,0,1,7.67566,3.1762,1.40036,1.40036,0,0,0,1.88159,0,1.32136,1.32136,0,0,0,0-1.87767l-.16227-.16741a13.52616,13.52616,0,1,0,.552,18.86116l-1.88218-1.88372a10.85235,10.85235,0,1,1-8.06478-18.10856Z"/><path class="cls-2" d="M96.4737,63.38456a1.26776,1.26776,0,0,0-1.1082.73839c-.2181.41476-7.95227,19.54645-7.95258,19.54645,0,0-7.73479-19.13169-7.95316-19.54645a1.267,1.267,0,0,0-1.10789-.73839,1.25029,1.25029,0,0,0-1.1761.96915c-.15382.54294-4.51785,24.62385-4.51785,24.62385a1.26706,1.26706,0,0,0-.02353.24129,1.19944,1.19944,0,0,0,2.37686.22925l3.77888-20.6S86.08181,86.86249,86.296,87.29143a1.2006,1.2006,0,0,0,2.23327,0c.21417-.42894,7.50585-18.44338,7.50585-18.44338l3.92849,21.42051h2.4375s-4.5972-25.37191-4.751-25.91485A1.25082,1.25082,0,0,0,96.4737,63.38456Z"/><path class="cls-2" d="M144.52511,63.38456a1.27135,1.27135,0,0,0-1.11605.758c-.21837.42832-10.00942,24.60937-10.00942,24.60937a1.21412,1.21412,0,0,0-.09229.46692,1.198,1.198,0,0,0,2.31352.43888l3.8024-9.34973h10.20729l4.05395,9.96056h2.58922s-10.419-25.69768-10.63319-26.126A1.26312,1.26312,0,0,0,144.52511,63.38456Zm-4.01776,14.26213,4.01776-9.883,4.02257,9.883Z"/><path class="cls-2" d="M197.13782,64.85835a1.33185,1.33185,0,0,0-1.332-1.32961H180.75732a1.3287,1.3287,0,0,0,0,2.65739h6.30894V90.26856h2.4354V66.18613h6.30415A1.33186,1.33186,0,0,0,197.13782,64.85835Z"/><path class="cls-3" d="M116.06206,29.12533a5.73633,5.73633,0,0,1-.49861,5.11963L109.174,48.61779l-.054.06514-2.31053-14.57869c-.18427-1.39926,1.31271-1.99622,2.19139-2.66854-.04373-.20633-.27146-.19518-.41265-.2929l-2.15819-.022-.06514-.06487a4.94419,4.94419,0,0,1,2.636-4.36057,5.12476,5.12476,0,0,1,5.65138.553A5.32954,5.32954,0,0,1,116.06206,29.12533Z"/><path class="cls-4" d="M104.29294,28.62613a5.1566,5.1566,0,0,1,.64,3.27588l-2.60339,16.69376c.01056.022-.01085.04389-.03228.05461l-.67294-1.345L95.09431,32.72685a5.06253,5.06253,0,0,1,6.76866-6.20491A5.4244,5.4244,0,0,1,104.29294,28.62613Z"/><path class="cls-5" d="M125.50952,35.65509a5.12575,5.12575,0,0,1-.29287,5.15267,8.54241,8.54241,0,0,1-2.45109,2.10463l-13.52643,9.285h-.03259l.152-.44478,7.16983-16.18412a5.1622,5.1622,0,0,1,5.29364-2.58183A5.22333,5.22333,0,0,1,125.50952,35.65509Z"/><path class="cls-6" d="M94.78,35.56854l7.4627,16.6289h-.11916L87.07826,41.827a4.96079,4.96079,0,0,1-1.63774-5.17408A5.07442,5.07442,0,0,1,94.78,35.56854Z"/><path class="cls-7" d="M129.4368,47.39209a5.12788,5.12788,0,0,1-.61867,5.09822,5.06429,5.06429,0,0,1-4.1544,1.95233l-16.043.01087,13.43957-9.35035a5.19275,5.19275,0,0,1,4.74048-.31474A5.26886,5.26886,0,0,1,129.4368,47.39209Z"/><path class="cls-8" d="M81.93661,47.39209a5.12816,5.12816,0,0,0,.61821,5.09822,5.06593,5.06593,0,0,0,4.15483,1.95233l16.04316.01087L89.31305,45.10316a5.19268,5.19268,0,0,0-4.74046-.31474A5.2689,5.2689,0,0,0,81.93661,47.39209Z"/></svg>
|
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 6.1 KiB |
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Comcast
|
||||
content_url: https://youtu.be/lmeFkH-rHII
|
||||
---
|
Before Width: | Height: | Size: 19 KiB |
|
@ -1 +0,0 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 215 127"><defs><style>.cls-1{fill:#fbfbfb;}.cls-2{fill:#0075c9;}</style></defs><title>kubernetes.io-logos</title><rect class="cls-1" x="-4.03751" y="-4.582" width="223.25536" height="134.51136"/><path class="cls-2" d="M60.85857,43.59905a2.41437,2.41437,0,0,0-2.38123-2.38123H19.43513a2.41437,2.41437,0,0,0-2.38123,2.38123V81.74831a2.41436,2.41436,0,0,0,2.38123,2.38122H58.47734a2.41436,2.41436,0,0,0,2.38123-2.38122ZM37.98886,70.884a11.98933,11.98933,0,0,0,3.72067-.74414.33416.33416,0,0,1,.39687.14882,14.28731,14.28731,0,0,0,2.87732,3.86949c.14883.24805-.14883.39687-.14883.39687a14.109,14.109,0,0,1-6.846,1.63709A13.89042,13.89042,0,0,1,23.7511,62.59926,13.42058,13.42058,0,0,1,37.74081,48.9072,15.13234,15.13234,0,0,1,45.82707,51.338c.5457.34726.5457.49609.39687.69452a29.88443,29.88443,0,0,0-2.282,3.72067.30167.30167,0,0,1-.49609.09922,10.304,10.304,0,0,0-6.00268-1.6867,7.97435,7.97435,0,0,0-7.987,8.3343A8.46744,8.46744,0,0,0,37.98886,70.884Zm12.15418.39686a3.86949,3.86949,0,1,1,3.8695-3.86949A3.87447,3.87447,0,0,1,50.143,71.28082Z"/><path class="cls-2" d="M68.64717,62.54966c0-5.95307,4.51441-10.021,10.269-10.021a8.91,8.91,0,0,1,8.08626,4.71285l-3.52224,1.73631a5.26387,5.26387,0,0,0-4.564-2.82771,5.99857,5.99857,0,0,0-6.05228,6.34994A5.99858,5.99858,0,0,0,78.91621,68.85a5.29072,5.29072,0,0,0,4.564-2.82772l3.52224,1.6867a8.9438,8.9438,0,0,1-8.08626,4.76246c-5.80424.04962-10.269-3.96871-10.269-9.92177"/><path class="cls-2" d="M88.73878,62.54966a10.09619,10.09619,0,1,1,10.07061,9.97139,9.73545,9.73545,0,0,1-10.07061-9.97139m15.97407,0c0-3.62145-2.33162-6.34994-5.90346-6.34994s-5.85385,2.72849-5.85385,6.34994c0,3.57184,2.282,6.34994,5.85385,6.34994s5.90346-2.7781,5.90346-6.34994"/><polygon class="cls-2" points="125.747 72.174 116.52 59.573 116.52 72.174 112.402 72.174 112.402 52.876 116.669 52.876 125.598 64.98 125.598 52.876 129.716 52.876 129.716 72.174 125.747 72.174"/><path class="cls-2" d="M133.18837,62.54966c0-5.95307,4.4648-10.021,10.26905-10.021a8.85137,8.85137,0,0,1,8.08625,4.71285l-3.52224,1.73631a5.26385,5.26385,0,0,0-4.564-2.82771,6.02732,6.02732,0,0,0-6.0523,6.34994,5.99858,5.99858,0,0,0,6.0523,6.34994,5.29073,5.29073,0,0,0,4.564-2.82772l3.52224,1.6867a8.94378,8.94378,0,0,1-8.08625,4.76246c-5.80425.04962-10.26905-3.96871-10.26905-9.92177"/><path class="cls-2" d="M154.22255,64.4844V52.87592h4.16714V64.33558a4.197,4.197,0,0,0,4.564,4.564c2.97654,0,4.51441-1.83554,4.51441-4.564V52.87592h4.21676V64.4844c0,4.81207-2.82771,8.08626-8.73117,8.08626s-8.73117-3.32381-8.73117-8.08626"/><path class="cls-2" d="M186.66678,72.17379l-3.8199-6.846h-3.02614v6.846H175.7032V52.82632H184.732c4.01833,0,6.49877,2.62927,6.49877,6.25072a5.55983,5.55983,0,0,1-4.21676,5.75464l4.36558,7.34211Zm.39688-13.09676a2.62258,2.62258,0,0,0-2.87731-2.62927h-4.316V61.6567h4.316a2.55935,2.55935,0,0,0,2.87731-2.57967"/><path class="cls-2" d="M198.12644,70.13982a2.45577,2.45577,0,0,1-4.91128,0,2.405,2.405,0,0,1,2.48044-2.38122A2.36249,2.36249,0,0,1,198.12644,70.13982Zm-4.316,0a1.86535,1.86535,0,0,0,1.88513,1.93475,1.9101,1.9101,0,1,0-1.88513-1.93475Zm1.48826,1.24023h-.5457V68.99882a4.18583,4.18583,0,0,1,.94257-.09922,1.60369,1.60369,0,0,1,.84336.19843.64015.64015,0,0,1,.248.5457.62217.62217,0,0,1-.49609.54571v.04961c.24805.09922.34727.248.44648.59531s.09922.49609.19843.59531h-.59531c-.09922-.09922-.09922-.29765-.19843-.59531a.45069.45069,0,0,0-.49609-.39686h-.24805l-.09921.94255Zm0-1.33945h.24805c.29766,0,.5457-.09922.5457-.34727,0-.19843-.14882-.34727-.49609-.34727-.14882,0-.248,0-.29766.04961v.64493Z"/></svg>
|
Before Width: | Height: | Size: 3.5 KiB |
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Concur
|
||||
content_url: http://searchitoperations.techtarget.com/news/450297178/Tech-firms-roll-out-Kubernetes-in-production
|
||||
---
|
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 215 127"><defs><style>.cls-1{fill:none;}.cls-2{fill:#fbfbfb;}.cls-3{clip-path:url(#clip-path);}.cls-4{fill:#ee3248;fill-rule:evenodd;}</style><clipPath id="clip-path"><rect class="cls-1" x="4.70501" y="-8.81268" width="206.90403" height="145.3255"/></clipPath></defs><rect class="cls-2" x="-3.37342" y="-3.34411" width="223.25536" height="134.51135"/><g class="cls-3"><g class="cls-3"><path class="cls-4" d="M28.02166,50.76936l7.69058-.0617c6.9525.12305,7.75228,4.1837,4.61435,13.41275-2.64567,7.87531-6.76768,12.67414-14.58165,12.61279h-6.091ZM169.22325,61.044c4.55274-11.01316,10.52065-15.19686,22.76431-15.50454,10.9518-.24609,15.81224,4.79908,11.813,17.41187C199.49376,76.67151,191.67987,82.209,179.86693,82.209c-12.98175.06134-16.24263-7.87514-10.64368-21.165m8.429.73843c2.83006-7.01411,6.95215-11.87463,13.04345-11.93633,5.47555-.06125,6.46007,3.938,3.99905,12.36706-3.13794,10.82842-7.69068,15.5659-13.90466,15.44286-6.89106-.06135-6.768-6.82946-3.13784-15.87359m-15.07382-8.67536,2.09172-6.02932a34.76316,34.76316,0,0,0-10.95146-1.66134c-7.62924-.0616-13.35114,2.33806-15.6892,7.69066-3.69162,8.183,1.4766,10.70564,7.69084,13.59749,9.10583,4.245,3.876,11.56684-4.86069,10.82842-3.50688-.3077-6.58311-1.90724-9.65961-3.38384l-1.96859,6.15264A33.79646,33.79646,0,0,0,142.64393,82.209c9.0444-.55369,14.64308-4.184,16.91972-9.90595,2.584-6.52159-1.41525-10.52064-7.38324-12.42789-12.42831-3.99939-4.98338-15.75088,10.398-6.76811M95.57659,46.15492a19.153,19.153,0,0,1,2.215,3.62993L87.76306,81.47059H93.854l8.36766-26.45618,9.59791,26.45618h8.61375l-.36939-.98451,10.89012-34.33116h-6.15273l-7.99827,25.34837-9.22879-25.34837c-3.999,0-7.99836.06135-11.99767,0m-34.39259,0a14.395,14.395,0,0,1,2.21468,3.62993L53.43173,81.47059H79.826L81.05656,77.533H63.21437L67.152,65.16635H78.96492l1.23051-3.87627H68.3825L71.95081,49.9695H89.17822L90.347,46.15492c-9.72121,0-19.44208.06135-29.163,0m-42.26817,0a16.4482,16.4482,0,0,1,2.21468,3.62993L11.102,81.47059h8.61366l5.04517-.06135c14.766,0,21.77988-7.32179,24.73333-16.85828,4.245-13.5973-.92316-18.33469-13.47418-18.33469Z"/></g></g></svg>
|
After Width: | Height: | Size: 2.2 KiB |
|
@ -0,0 +1,110 @@
|
|||
---
|
||||
title: Denso Case Study
|
||||
linkTitle: Denso
|
||||
case_study_styles: true
|
||||
cid: caseStudies
|
||||
css: /css/case-studies-gradient.css
|
||||
logo: denso_featured_logo.svg
|
||||
featured: true
|
||||
weight: 4
|
||||
quote: >
|
||||
We got Kubernetes experts involved on our team, and it dramatically accelerated development speed.
|
||||
---
|
||||
|
||||
|
||||
<div class="article image overlay" style="background-image: url('/images/Denso2.jpg')">
|
||||
<h1> CASE STUDY: Denso</h1>
|
||||
<div class="subhead">How DENSO Is Fueling Development on the Vehicle Edge with Kubernetes</div>
|
||||
</div>
|
||||
|
||||
<div class="details">
|
||||
Company <b>Denso</b> Location <b>Japan</b> Industry <b>Automotive, Edge</b>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<section class="section1">
|
||||
<div class="colsgradient">
|
||||
<div class="col1">
|
||||
<h2>Challenge</h2>
|
||||
DENSO Corporation is one of the biggest automotive components suppliers in the world. With the advent of connected cars, the company launched a Digital Innovation Department to expand into software, working on vehicle edge and vehicle cloud products. But there were several technical challenges to creating an integrated vehicle edge/cloud platform: "the amount of computing resources, the occasional lack of mobile signal, and an enormous number of distributed vehicles," says R&D Product Manager Seiichi Koizumi.
|
||||
|
||||
|
||||
<h2>Solution</h2>
|
||||
Koizumi’s team realized that because mobility services evolve every day, they needed the flexibility of the cloud native ecosystem for their platform. After considering other orchestrators, DENSO went with Kubernetes for orchestration and added Prometheus, Fluentd, Envoy, Istio, and Helm to the platform. Today, DENSO is using a vehicle edge computer, a private Kubernetes cloud, and managed Kubernetes (GKE, EKS, AKS).
|
||||
|
||||
<h2>Impact</h2>
|
||||
Critical layer features can take 2-3 years to implement in the traditional, waterfall model of development at DENSO. With the Kubernetes platform and agile methods, there’s a 2-month development cycle for non-critical software. Now, ten new applications are released a year, and a new prototype is introduced every week. "By utilizing Kubernetes managed services, such as GKE/EKS/AKS, we can unify the environment and simplify our maintenance operation," says Koizumi.
|
||||
</div>
|
||||
</section>
|
||||
<div class="article image overlay" style="background-image: url('/images/Denso1.png');">
|
||||
<div class="quotetext">
|
||||
"Another disruptive innovation is coming, so to survive in this situation, we need to change our culture."
|
||||
<p><div class="quoteauthortext">- SEIICHI KOIZUMI, R&D PRODUCT MANAGER, DIGITAL INNOVATION DEPARTMENT AT DENSO</div></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<section class="section2">
|
||||
<div class="fullcol">
|
||||
<h4>Spun off from Toyota in 1949, DENSO Corporation is one of the top automotive suppliers in the world today, with consolidated net revenue of $48.3 billion.
|
||||
</h4>
|
||||
|
||||
<p>The company’s mission is "contributing to a better world by creating value together with a vision for the future"—and part of that vision in recent years has been development on the vehicle edge and vehicle cloud.</p>
|
||||
|
||||
<p>With the advent of connected cars, DENSO established a Digital Innovation Department to expand its business beyond the critical layer of the engine, braking systems, and other automotive parts into the non-critical analytics and entertainment layer. Comparing connected cars to smartphones, R&D Product Manager Seiichi Koizumi says DENSO wants the ability to quickly and easily develop and install apps for the "blank slate" of the car, and iterate them based on the driver’s preferences. Thus "we need a flexible application platform," he says. </p>
|
||||
|
||||
<p>But working on vehicle edge and vehicle cloud products meant there were several technical challenges: "the amount of computing resources, the occasional lack of mobile signal, and an enormous number of distributed vehicles," says Koizumi. "We are tackling these challenges to create an integrated vehicle edge/cloud platform."</p>
|
||||
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="greybanner">
|
||||
<div class="greyquotetext">
|
||||
"We got Kubernetes experts involved on our team, and it dramatically accelerated development speed."<p><div class="quoteauthortext">— SEIICHI KOIZUMI, R&D PRODUCT MANAGER, DIGITAL INNOVATION DEPARTMENT AT DENSO</div></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="section3">
|
||||
<div class="fullcol">
|
||||
<p>
|
||||
Koizumi’s team realized that because mobility services evolve every day, they needed the flexibility of the cloud native ecosystem for their platform. As they evaluated technologies, they were led by these criteria: Because their service-enabler business needed to support multiple cloud and on-premise environments, the solution needed to be cloud agnostic, with no vendor lock-in and open governance. It also had to support an edge-cloud integrated environment.</p>
|
||||
<p>
|
||||
After considering other orchestrators, DENSO went with Kubernetes for orchestration and added Prometheus, Fluentd, Envoy, Istio, and Helm to the platform. During implementation, the team used "design thinking to clarify use cases and their value proposition," says Koizumi. Next, an agile development team worked on a POC, then an MVP, in DevOps style. "Even in the development phase, we are keeping a channel to end users," he adds. </p>
|
||||
<p>
|
||||
One lesson learned during this process was the value of bringing in experts. "We tried to learn Kubernetes and cloud native technologies from scratch, but it took more time than expected," says Koizumi. "We got Kubernetes experts involved on our team, and it dramatically accelerated development speed."</p>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<div class="article image overlay" style="background-image: url('/images/Denso4.jpg');">
|
||||
<div class="quotetext">
|
||||
"By utilizing Kubernetes managed services, such as GKE/EKS/AKS, we can unify the environment and simplify our maintenance operation." <p><div class="quoteauthortext">- SEIICHI KOIZUMI, R&D PRODUCT MANAGER, DIGITAL INNOVATION DEPARTMENT AT DENSO</div></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="section5">
|
||||
<div class="fullcol">
|
||||
<p>
|
||||
Today, DENSO is using a vehicle edge computer, a private Kubernetes cloud, and managed Kubernetes on GKE, EKS, and AKS. "We are developing a vehicle edge/cloud integrated platform based on a microservice and service mesh architecture," says Koizumi. "We extend cloud into multiple vehicle edges and manage it as a unified platform."</p>
|
||||
<p>
|
||||
Cloud native has enabled DENSO to deliver applications via its new dash cam, which has a secure connection that collects data to the cloud. "It’s like a smartphone," he says. "We are installing new applications and getting the data through the cloud, and we can keep updating new applications all through the dash cam."</p>
|
||||
<p>
|
||||
The unified cloud native platform, combined with agile development, has had a positive impact on productivity. Critical layer features—those involving engines or braking systems, for example—can take 2-3 years to implement at DENSO, because of the time needed to test safety, but also because of the traditional, waterfall model of development. With the Kubernetes platform and agile methods, there’s a 2-month development cycle for non-critical software. Now, ten new applications are released a year, and with the department’s scrum-style development, a new prototype is introduced every week. </p>
|
||||
<p>
|
||||
Application portability has also led to greater developer efficiency. "There’s no need to care about differences in the multi-cloud platform anymore," says Koizumi. Now, "we are also trying to have the same portability between vehicle edge and cloud platform."
|
||||
</p>
|
||||
<p>
|
||||
Another improvement: Automotive Tier-1 suppliers like DENSO always have multiple Tier-2 suppliers. "To provide automotive-grade high-availability services, we tried to do the same thing on a multi-cloud platform," says Koizumi. Before Kubernetes, maintaining two different systems simultaneously was difficult. "By utilizing Kubernetes managed services, such as GKE/EKS/AKS, we can unify the environment and simplify our maintenance operation," he says.
|
||||
</p>
|
||||
<p>
|
||||
Cloud native has also profoundly changed the culture at DENSO. The Digital Innovation Department is known as "Noah’s Ark," and it has grown from 2 members to 70—with plans to more than double in the next year. The way they operate is completely different from the traditional Japanese automotive culture. But just as the company embraced change brought by hybrid cars in the past decade, Koizumi says, they’re doing it again now, as technology companies have moved into the connected car space. "Another disruptive innovation is coming," he says, "so to survive in this situation, we need to change our culture."
|
||||
</p>
|
||||
<p>
|
||||
Looking ahead, Koizumi and his team are expecting serverless and zero-trust security architecture to be important enhancements of Kubernetes. They are glad DENSO has come along for the ride. "Mobility service businesses require agility and flexibility," he says. "DENSO is trying to bring cloud native flexibility into the vehicle infrastructure."
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
Before Width: | Height: | Size: 22 KiB |
|
@ -1 +0,0 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 215 127"><defs><style>.cls-1{fill:#fbfbfb;}.cls-2{fill:#e53238;}.cls-3{fill:#0064d2;}.cls-4{fill:#f5af02;}.cls-5{fill:#86b817;}</style></defs><title>kubernetes.io-logos</title><rect class="cls-1" x="-3.55202" y="-3.16104" width="223.25536" height="134.51136"/><path id="e" class="cls-2" d="M44.41375,44.77747c-12.0763,0-22.13948,5.12337-22.13948,20.58035,0,12.24533,6.76676,19.95671,22.4513,19.95671,18.46144,0,19.64488-12.16112,19.64488-12.16112H55.425S53.507,79.7017,44.17988,79.7017c-7.59672,0-13.06058-5.1318-13.06058-12.32478H65.30592V62.86323c0-7.11611-4.51743-18.08577-20.89217-18.08577Zm-.31183,5.76874c7.23129,0,12.16112,4.43,12.16112,11.06973H31.31716C31.31716,54.56709,37.75185,50.54621,44.10192,50.54621Z"/><path id="b" class="cls-3" d="M65.29958,29.80994V77.5521c0,2.71-.19342,6.51514-.19342,6.51514h8.53207s.30624-2.73291.30624-5.23052c0,0,4.21539,6.59475,15.67735,6.59475,12.06991,0,20.26852-8.37974,20.26852-20.38547,0-11.16875-7.5307-20.15159-20.249-20.15159-11.90983,0-15.61067,6.43136-15.61067,6.43136V29.80994ZM87.43905,50.79956c8.1964,0,13.40842,6.08315,13.40842,14.24644,0,8.75365-6.0197,14.48031-13.35,14.48031-8.748,0-13.46688-6.83041-13.46688-14.40235C74.03064,58.06838,78.265,50.79956,87.43905,50.79956Z"/><path id="a" class="cls-4" d="M131.09435,44.77747c-18.16788,0-19.33306,9.94784-19.33306,11.53747h9.04288s.47421-5.80771,9.66654-5.80771c5.97332,0,10.602,2.73408,10.602,7.99048v1.87094h-10.602c-14.07492,0-21.51583,4.11747-21.51583,12.47294,0,8.223,6.87517,12.69707,16.16611,12.69707,12.6621,0,16.741-6.99654,16.741-6.99654,0,2.78284.21455,5.52512.21455,5.52512h8.039s-.31183-3.39915-.31183-5.57384V59.69628c0-12.325-9.94141-14.91881-18.70941-14.91881Zm9.97836,21.204v2.49459c0,3.25362-2.00772,11.34258-13.82743,11.34258-6.47244,0-9.24752-3.23023-9.24752-6.97705,0-6.81622,9.34533-6.86012,23.07494-6.86012Z"/><path id="y" class="cls-5" d="M144.93431,46.33816h10.17324l14.6,29.25016,14.56661-29.25016h9.2155L166.95684,98.41267H157.2903l7.65638-14.51648Z"/></svg>
|
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 7.1 KiB |
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Ebay
|
||||
content_url: http://www.nextplatform.com/2015/11/12/inside-ebays-shift-to-kubernetes-and-containers-atop-openstack/
|
||||
---
|
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 22 KiB |
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Goldman Sachs
|
||||
content_url: http://blogs.wsj.com/cio/2016/02/24/big-changes-in-goldmans-software-emerge-from-small-containers/
|
||||
---
|
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 27 KiB |