Introduction
Dans le cadre de ma préparation à l’examen de certifiation d’administration Kubernetes (CKA), je me prépare quelques exercices pratiques à mettre en oeuvre. Si vous êtes intéressés, je vous propose ceux-ci, avec une solution possible. N’hésitez pas à me faire part de vos commentaires, critiques ou de vos propres solutions pour en discuter !
Challenge
Un nouveau collaborateur Bobby vient d’arriver dans votre société, et il souhaite pouvoir se connecter à un cluster Kubernetes existant avec kubectl afin de gérer complètement le namespace developer
.
Comment faire?
Solution
Note
Au moment de l’écriture de ce billet, l’examen CKA est basé sur Kubernetes 1.18.
Les solutions proposées sont donc basées sur cette version.
Création d’un certificat Client
La première chose à faire est de générer une CSR (Certificate Signing Request). Il est possible d’utiliser OpenSSL pour cela, mais pour cette fois c’est CFSSL qui sera utilisé.
Pour cela, il faut préparer un fichier JSON qui décrit les informations du certificat que l’on souhaite générer :
{
"CN": "bobby",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"O": "developers"
}
]
}
Nous le passons ensuite à CFSSL pour la génération proprement dite:
cfssl genkey bobby-admin.json | cfssljson -bare bobby-admin
Le résultat de cette commande est la création de deux fichiers :
- bobby-admin-key.pem : la clé privée
- bobby-admin-key.csr : la demande de signature
Signature de la CSR par Kubernetes
Il faut maintenant signer la CSR par l’autorité de notre cluster Kubernetes afin de récupérer un certificat valide qui sera utilisé pour l’authentification.
Pour cela, nous allons créer une resource de type CertificateSigningRequest de l’API certificates.k8s.io/v1beta1
, dont la représentation YAML peut être créée via cette commande :
cat > bobby-admin-csr.yml <<EOF
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
name: bobby-authentication
spec:
groups:
- system:authenticated
request: $(cat bobby-admin.csr | base64 | tr -d '\n')
usages:
- digital signature
- key encipherment
- server auth
- client auth
EOF
Celle-ci est ensuite importée dans Kubernetes via kubectl
:
$> kubectl apply -f bobby-authentication.yaml
certificatesigningrequest.certificates.k8s.io/bobby-authentication
On peut vérifier que cette CSR est bien présente, et en attente d’être validée :
$> kubectl get csr bobby-authentication
NAME AGE SIGNERNAME REQUESTOR CONDITION
bobby-authentication 4m50s kubernetes.io/legacy-unknown kubernetes-admin Pending
Pour signer celle-ci, kubectl est une nouvelle fois notre ami :
# Validation de la CSR
$> kubectl certificate approve bobby-authentication
certificatesigningrequest.certificates.k8s.io/bobby-authentication approved
# Vérification de l'état de la CSR, qui est bien approuvée
$> kubectl get csr bobby-authentication
NAME AGE SIGNERNAME REQUESTOR CONDITION
bobby-authentication 6m33s kubernetes.io/legacy-unknown kubernetes-admin Approved,Issued
Reste maintenant à extraine le certificat généré via kubectl
:
kubectl get csr bobby-authentication -o jsonpath='{.status.certificate}' | base64 --decode > bobby-admin.crt
Configuration de kubectl
Tip
Dans les exemples de commandes suivantes, le paramètre --kubeconfig=bobby-config
est proposé à chaque commande afin de permettre de différencier les commandes kubectl
utilisée par un utilisateur admin existant, des commandes kubectl
sur le poste de Bobby.
Il serait cependant possiblle de définir la variables d’environment KUBECONFIG
pointant vers ce fichier afin d’éviter cette verbosité :
# Un seul fichier specifique
export KUBECONFIG=/path/to/bobby-config
# Ou si l'on souhaite avoir plusieurs fichiers de configuration
export KUBECONFIG=/path/to/bobby-config:/path/to/other-config
Afin de configurer kubectl, il est nécessaire d’avoir :
- Le certificat de l’autorité de certification, que l’on peut trouver sur le master dans
/etc/kubernetes/pki/ca.crt
- L’URL de l’API server
- Le certificat client, qui vient d’être généré
- La clé privée liée à ce certificat
API_URL=https://10.0.1.100:6443
kubectl config --kubeconfig=bobby-config set-cluster development --server=$API_URL --certificate-authority=ca.crt
kubectl config --kubeconfig=bobby-config set-credentials bobby-creds --client-certificate=bobby-admin.crt --client-key=bobby-admin-key.pem
kubectl config --kubeconfig=bobby-config set-context bobby --cluster=development --namespace=developer --user=bobby-creds
kubectl --kubeconfig=bobby-config use-context bobby
Si tout s’est passé correctement, nous devrions pouvoir appeler notre cluster avec kubectl en distant.
Tentons de lister les pods dans le namespace developer
$> kubectl --kubeconfig=bobby-config get pods
Error from server (Forbidden): pods is forbidden: User "developer-admin" cannot list resource "pods" in API group "" in the namespace "developer"
La connexion est opérationnelle, mais actuellement, notre utilisateur n’a aucun droit sur le namespace developer
.
Il ne peut rien faire pour le moment !
Configuration RBAC pour l’utilisateur
La première chose à faire est de créer un role dans notre namespace. Le YAML suivant pourrait faire l’affaire :
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: developer-admin-role
namespace: developer
rules:
- apiGroups: ["", "extensions", "apps"]
resources: ["*"]
verbs: ["*"]
- apiGroups: ["batch"]
resources:
- jobs
- cronjobs
verbs: ["*"]
Un coup de kubectl apply -f developer-admin-role.yml
pour créer le rôle et il l’étape suivant sera de lier l’utilisateur bobby à ce rôle :
$> kubectl create rolebinding bobby-developer-admin-role --role=developer-admin-role --user=bobby -n developer
rolebinding.rbac.authorization.k8s.io/developer-admin-role created
Et tada :
$> kubectl --kubeconfig=bobby-config run test-nginx --image nginx
pod/test-nginx created
$> kubectl --kubeconfig=bobby-config get pods
NAME READY STATUS RESTARTS AGE
test-nginx 1/1 Running 0 37s
Et voila :-)
D’autres exercices ?
D’autres petits challenges viendront sans doute par la suite, mais en attendant si vous voulez vous entrainer pour l’examen CKA, je vous conseille ces deux sites (en anglais):
Ce dernier est payant, mais franchement bien fait ! Et a priori dans les mêmes conditions que l’examen lui même (Web Interface, plusieurs contextes/clusters), et a priori un peu plus compliqué que l’examen (d’après les retours que j’ai pu lire, n’ayant pas encore passé moi même l’examen).
Remerciements
Merci à Aurélie Vache pour la relecture :-)