resolve conflict

pull/21746/head
inductor 2020-06-15 02:59:15 +09:00
commit 298382169c
2451 changed files with 127381 additions and 564546 deletions

View File

@ -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

View File

@ -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.
-->

2
.gitignore vendored
View File

@ -33,4 +33,4 @@ resources/
# Netlify Functions build output
package-lock.json
functions/
node_modules/
node_modules/

16
.htmltest.yml Normal file
View File

@ -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"

View File

@ -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
View File

@ -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

View File

@ -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

View File

@ -36,7 +36,7 @@
> यदि आप डॉकर के बिना स्थानीय रूप से वेबसाइट चलाना पसंद करते हैं, तो नीचे Hugo का उपयोग करके स्थानीय रूप से साइट चलाना देखें।
यदि आप डॉकर के बिना स्थानीय रूप से वेबसाइट चलाना पसंद करते हैं, तो नीचे दिए गए Hugo का उपयोग करके स्थानीय रूप से [साइट को चलाने](#running-the-site-locally-using-hugo) का तरीका देखें।
यदि आप डॉकर के बिना स्थानीय रूप से वेबसाइट चलाना पसंद करते हैं, तो नीचे दिए गए Hugo का उपयोग करके स्थानीय रूप से [साइट को चलाने](#hugo-का-उपयोग-करते-हुए-स्थानीय-रूप-से-साइट-चलाना) का तरीका देखें।
यदि आप [डॉकर](https://www.docker.com/get-started) चला रहे हैं, तो स्थानीय रूप से `कुबेरनेट्स-ह्यूगो` Docker image बनाएँ:

View File

@ -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:

View File

@ -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).
## Спасибо!

85
README-uk.md Normal file
View File

@ -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
View File

@ -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!

View File

@ -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

View File

@ -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

View File

@ -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"]

View File

@ -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>

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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.

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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.

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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/) | &#x2714; | | | | | |
{{% /capture %}}

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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/)

View File

@ -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 %}}

View File

@ -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 %}}

View File

@ -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>

View File

@ -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 >}}

View File

@ -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 >}}

View File

@ -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: Todays post is by Sandeep Dinesh, Developer Advocate, Google Cloud Platform, showing how to run a database in a container._
_Editor's note: Todays 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 cant run a database in a container. “Containers are stateless!” they say, and “databases are pointless without state!”
Conventional wisdom says you cant 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 youve 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 youve 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. Lets 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. Lets 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, youll 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/).
Ive created the configuration files for these already, and you can clone the example from GitHub:
Ive 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)
Lets 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 dont 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
```
Its 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\_?
```
Thats it!
Thats 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._

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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, lets 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

View File

@ -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

View File

@ -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 lets 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 lets 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 pods IP as the upstream local address, instead of the services 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
```

View File

@ -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

View File

@ -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 thats 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 hints 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, dont 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 -->

View File

@ -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, whats 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.
## Wasnt it already Beta before 1.18?
Yes, Server-side Apply has been Beta since 1.16, but it didnt track the owner for fields associated with objects that had not been applied. This means that most objects didnt 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.
## Whats 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

View File

@ -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
Its 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. Heres 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).

View File

@ -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 drivers 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). Were 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

View File

@ -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 planes 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 requests “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 its 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 elephants 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.
## Whats missing? When will there be a beta?
Were already planning a few enhancements based on alpha and there will be more as users send feedback to our community. Heres 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!

View File

@ -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)

View File

@ -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

View File

@ -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**.

View File

@ -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.

View File

@ -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 its 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).

View File

@ -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)

View File

@ -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.

View File

@ -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
theyre 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 Im 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, Id 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, Ive 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, lets 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. Id 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 theyre 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, theyre 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 theyre 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 theyre 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 frequencyinverse 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 theyre
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. Ive 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
were 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 were 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 Id 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. Thats 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. Thats pretty neat, isnt
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 lets 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

View File

@ -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.

View File

@ -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, well walk through whats 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
### Whats 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 users 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)!

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 224 KiB

View File

@ -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 Babylons Medical AI Innovations</div>
</div>
<div class="details">
Company &nbsp;<b>Babylon</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Location &nbsp;<b>United Kingdom</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Industry &nbsp;<b>AI, Healthcare</b>
</div>
<hr>
<section class="section1">
<div class="colsgradient">
<div class="col1">
<h2>Challenge</h2>
A large number of Babylons products leverage machine learning and artificial intelligence, and in 2019, there wasnt 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>Babylons 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 doctors appointment. Through Babylons 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>Thats 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 didnt 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ées team was tasked with building a self-service platform to help Babylons 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 companys 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, its pretty much instantaneous,” says Vallée. </p>
<p>
Another important type of work thats done on the platform is clinical validation for new applications such as Babylons 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 theyre 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>
Babylons road map for cloud native involves onboarding all of the companys 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. “Its kind of a complex problem and theres 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@ -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 &nbsp;<b>Booking.com</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Location &nbsp;<b>Netherlands</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Industry &nbsp;<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 wasnt 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. “Were not claiming that you can just use it with your eyes closed. Developers need to do some learning, and were going to do everything we can to make sure they have access to that knowledge.”
<h2>Impact</h2>
Despite the learning curve, theres 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 didnt. 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. Its 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 didnt 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 companys 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>
Iacoboaias 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 OpenShifts built-in Ansible playbooks to Puppet deployments, which are used for the rest of Bookings 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. “Were not claiming that you can just use it with your eyes closed. Developers need to do some learning, and were 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, theres been a great uptick in adoption of the new Kubernetes platform. “I think the reason weve been able to strike this bargain successfully is that were not asking them to learn a proprietary app system,” says Tyler. “Were asking them to learn something thats open source, where the knowledge is transferable. Theyre 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 havent seen that kind of community engagement around a particular platform product internally before,” says Tyler. “It helps a lot that its 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, its 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>
Theres 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 didnt. On the new platform, it takes 10 minutes. “We have a tutorial. You follow the tutorial. Your code is running. Then, its 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, its just Kubernetes. If youre a pro Kubernetes user, heres a Kubernetes API, just like you get from GKE or AKS. Were 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. “Its 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, theyre kind of far apart, right?” says Tyler. “But weve 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>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -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 &nbsp;<b>Booz Allen Hamilton</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Location &nbsp;<b>United States</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Industry &nbsp;<b>Government</b>
</div>
<hr>
<section class="section1">
<div class="colsgradient">
<div class="col1">
<h2>Challenge</h2>
In 2017, Booz Allen Hamiltons 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 Hamiltons 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, Folkoffs 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 theres 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, thats the problem were 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, Folkoffs 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 Hamiltons 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, theres a lot of focus on scale, and so theres a lot of comfort knowing that as the project grows, were 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 governments 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, were starting to see even more interest,” says Chief Technologist Josh Boyd. Adds Folkoff: “With CNCF, theres a lot of focus on scale, and so theres a lot of comfort knowing that as the project grows, were 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 didnt 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 days 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 theres 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, thats the problem were 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 dont 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 days 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 youre doing. You dont have these onesies and twosies unicorn servers anymore. Now everything that you deploy is deployed in the same way, its all instrumented the same way, and its all built and deployed the same way through our CI/CD processes.”</p>
<p>
They also see a push toward re-platforming. “Theres still a lot of legacy workloads out there,” says Boyd. “Weve 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 its 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 theyve 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>

View File

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -1,4 +0,0 @@
---
title: CCP Games
content_url: https://cloud.google.com/customers/ccp-games/
---

View File

@ -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')">

View File

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -1,4 +0,0 @@
---
title: Comcast
content_url: https://youtu.be/lmeFkH-rHII
---

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

@ -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

View File

@ -1,4 +0,0 @@
---
title: Concur
content_url: http://searchitoperations.techtarget.com/news/450297178/Tech-firms-roll-out-Kubernetes-in-production
---

View File

@ -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

View File

@ -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 &nbsp;<b>Denso</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Location &nbsp;<b>Japan</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Industry &nbsp;<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>
Koizumis 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, theres 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 companys 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 drivers 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>
Koizumis 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. "Its 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, theres a 2-month development cycle for non-critical software. Now, ten new applications are released a year, and with the departments scrum-style development, a new prototype is introduced every week. </p>
<p>
Application portability has also led to greater developer efficiency. "Theres 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 "Noahs 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, theyre 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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

View File

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

View File

@ -1,4 +0,0 @@
---
title: Ebay
content_url: http://www.nextplatform.com/2015/11/12/inside-ebays-shift-to-kubernetes-and-containers-atop-openstack/
---

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

View File

@ -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/
---

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Some files were not shown because too many files have changed in this diff Show More