На сервере надо разрешить доступ к kube-apiserver. Замените адрес API_SERVER, если он другой. Выполните следующуее на всех входящий серверах, которые будут включены в DNS запись нашего сервера (например kapi.example.com). В DNS запись можно включить, например, несколько серверов из группы ingress. В нашем случае они доступны через внешние IP VLAN.
API_SERVER=10.118.12.100
cat <<EOF > /etc/local.d/iptables.start
#!/bin/sh
iptables -t mangle -I PREROUTING -i wan0 -p tcp --dport 6443 -j MARK --set-mark 1
iptables -t nat -I PREROUTING -m mark --mark 1 -j DNAT --to-destination $API_SERVER
iptables -t nat -I POSTROUTING -m mark --mark 1 -j MASQUERADE
EOF
chmod +x /etc/local.d/iptables.start
rc-update add local default
openrc
rc-service local start
Если FQDN, указывающий на kube-apiserver (например kapi.example.com) не включен в сертификат сервера, то сертификат надо исправить перегенерировать. Сначала обновляем конфигурацию сервера. Потом на каждом сервере, включенным в DNS запись (у нас kapi.example.com) удаляем старые сертификаты, пересоздаем сертификаты и перезапускаем kubelet. Последней командой можно зайти на ip сервера извне и проверить, какие адреса включены в сертификат.
kubeadm config view >kubeadmconf.yml
# Add kube-apiserver FQDN to apiServer.certSANs, e.g. kapi.example.com
vi kubeadmconf.yml
# Deprecated, but works. Proposes to use instead: kubeadm init phase upload-config
kubeadm config upload from-file --config kubeadmconf.yml
# Do the rest on each server
# Check cert before
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text -noout|less
# Recreate
rm /etc/kubernetes/pki/apiserver.*
kubeadm init phase certs apiserver --config=kubeadmconf.yml
# Recheck
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text -noout|less
# Restart kubelet
rc-service kubelet restart
# Check certificate externally.
openssl s_client -connect <ip or fqdn>:6443 | openssl x509 -noout -text
Для включения OIDC, необходимо в kube-apiserver добавить опции, проверящие что OIDC JWT Token выдан именно нашим OIDC провайдером, которому мы доверяем. Например в случае с Google это:
- issuer-url: https://accounts.google.com
- client-id: xxx.apps.googleusercontent.com
- client-secret: xxx
Получение аккаунта описано, например, тут и тут.
Далее необходимо добавить опции в apiserver. При добавлении новой вершины в кластер, kubeadm использует данные из
конфигурации кластера. При уже добавленной вершине, данные берутся из файла /etc/kubernetes/manifests/kube-apiserver.yaml
.
На текущий момент (июль 2020) мне неизвестен автоматический способ применения конфигурации сразу и везде, поэтому
необходимо поменять конфигурацию и обновить manifest на всех узлах Control Plane. Ниже описаны из
# Add this to kubeadmconf.yml (see below)
apiServer:
extraArgs:
# Add only following 4 lines. The rest is already there.
oidc-client-id: xxx.apps.googleusercontent.com
oidc-issuer-url: https://accounts.google.com
oidc-username-claim: email
oidc-groups-claim: groups
# Add this to /etc/kubernetes/manifests/kube-apiserver.yaml on all Control Plane nodes
spec:
containers:
- command:
- kube-apiserver
# Add only following 3 lines. The rest is already there.
- --oidc-issuer-url=https://accounts.google.com
- --oidc-username-claim=email
- --oidc-client-id=301523111073-hapgi8mcivo3ci1uv0tlqnspq4rtme84.apps.googleusercontent.com
Команды, которые необходимо выполнить:
kubeadm config view >kubeadmconf.yml
# Add the info described above
vi kubeadmconf.yml
# Deprecated, but works. Proposes to use instead: kubeadm init phase upload-config
kubeadm config upload from-file --config kubeadmconf.yml
# Do the next lines on all Control Plane nodes.
# Edit the file as described above
vi /etc/kubernetes/manifests/kube-apiserver.yaml
# Restart kubelet
rc-service kubelet restart
TODO: перегенерировать конфиг можно в автоматическом режиме с помощью kubeadm.
Install kubectl
: https://kubernetes.io/docs/tasks/tools/install-kubectl/
# MacOS
brew install kubectl
Install krew
packet manager for kubectl
: https://krew.sigs.k8s.io/docs/user-guide/setup/install/
(
set -x; cd "$(mktemp -d)" &&
curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/krew.{tar.gz,yaml}" &&
tar zxvf krew.tar.gz &&
KREW=./krew-"$(uname | tr '[:upper:]' '[:lower:]')_amd64" &&
"$KREW" install --manifest=krew.yaml --archive=krew.tar.gz &&
"$KREW" update
)
Add $HOME/.krew/bin
to PATH, e.g. in .bashrc
Check if krew is working:
kubectl krew
Install kubectx
, kubens
, and fzf
:
https://github.com/ahmetb/kubectx#installation
https://github.com/junegunn/fzf
# MacOS
brew install kubectx fzf
# For fzf keybinding (see https://github.com/junegunn/fzf#key-bindings-for-command-line)
/usr/local/opt/fzf/install
# MacOS
brew install bash-completion
Add lines e.g. to your .bashrc (or whatever was recommended after brew install above:
[ -r /usr/local/etc/profile.d/bash_completion.sh ] && . /usr/local/etc/profile.d/bash_completion.sh
To apply in the current session:
. ~/.bashrc
You can find more completion packages for bash-completion by running
# MacOS
brew search completion
Kubectl bash-completion:
echo 'source <(kubectl completion bash)' >>~/.bashrc
# For `k` alias:
echo 'alias k=kubectl' >>~/.bash_profile
echo 'complete -F __start_kubectl k' >>~/.bash_profile
Install oidc-login on your client machine:
kubectl krew install oidc-login
Create the ~/.kube/config using info below. Get missing data like CA from server's file /etc/kubernetes/admin.conf
.
The extra-scopes
field is needed if extra claims are needed for auth. Distribute the result config to engineers and
provide it to new engineers on onboarding.
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: <CA data>
server: https://kapi.viplay.dev:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
namespace: default
user: oidc
name: oidc@kubernetes
current-context: oidc@kubernetes
kind: Config
preferences: {}
users:
- name: oidc
user:
auth-provider:
config:
client-id: xxx.apps.googleusercontent.com
client-secret: xxx
extra-scopes: email
idp-issuer-url: https://accounts.google.com
name: oidc
Using kubectl
:
# To login
kubectl oidc-login
# Now kubectl should be working. Test by running e.g.:
kubectl cluster-info
Note, that Google OIDC doesn't provide refresh token. So user would need to re-login every hour. To avoid that it is
recommended to user some OIDC proxy, like dex
, AuthZ
or Keycloak
.
Final token is provided to kube-apiserver. It confirmes the signature, extracts the claims, checks issuer-id. Final
username depends on a chosen claim (--oidc-username-claim
argument):
- If claim is
email
, then username is the value of that claim. - If claim is anything else then username is
<iss claim value>#<claim value defined by oidc-username-claim>
, e.g. with Google OIDC and sub claim equal to12345
the value ishttps://accounts.google.com#12345
Links: