k8s: подготовка к CKS

Привет всем, в продолжении CKA сегодня получил следующий сертификат CKS — Certified Kubernetes Security Specialist (ID Number: LF-lq76nh25g0) и хотел бы поделиться рекомендациями для успешной сдачи экзамена. Не претендую на истину в последней инстанции, а лишь делюсь личным опытом и впечатлениями. Возможно кому то будет полезно.

Казалось бы, у нас нет ничего особого нового, мы просто поменяли контекст с общего на безопасность, и если CKA был относительно не сложным экзаменом, то вот CKS был прямо испытанием. Я смог пройти его только со второй попытки, в первой набрал 64% из необходимых 67%, вторая попытка была успешная и завершилась с результатом 83%.

И так, основная проблема, как бы это странно не звучало — время, а точнее его не хватка. Времени сильно не хватает. Напомню, что продолжительность экзамена 120 минут, вам дается 16–18 вопросов, лично у меня было 16, т.е. в среднем 7,5 минуты на вопрос. Но в отличие от CKA здесь задачи более объемные и как правило требуют больше времени на решение.

Теория

Здесь не будет ничего эдакого, я купил курс на Udemy — «https://kodekloud.com/courses/certified-kubernetes-security-specialist-cks/» от уже известного нам по первой статье Mumshad Mannambeth. На этот раз на Udemy я не брал никакие курсы.

А так же курс на youtube

Практика

Несмотря на наличие mock экзаменов в теоретическом курсе, практики будет явно недостаточно.

Для получения практики я использовал следующие курсы/лабы

https://kodekloud.com/courses/kubernetes-challenges/

https://kodekloud.com/courses/cks-challenges

https://killer.sh/cks

Напоминаю, как показала практика общения в slack канале killer.sh, не все люди знают, что при покупке экзамена, вы получаете две полноценные сессии у killer.sh. Они очень сильно отличаются от бесплатных заданий. Поэтому я очень рекомендую пройти их и разобрать непонятные моменты.

Ссылка на эмулятор будет доступна на странице самого экзамена

4e5c828d6d600ac17b6fe4c185f85d1a.png

Не обращайте внимание на название экзамена, после получения сертификата ссылка на эмулятор пропадает, но принцип будет тот же. Сама сессия представляет приближенное к реальному окружение, где вам дается 22 вопроса и 36 часов, т.е. окружение будет доступно в течение 36 часов с момента его создания. Для каждого экзамена доступно две сессии. Если нужна будет еще дополнительная сессия, то придется покупать отдельно. Стоимость каждой дополнительной сессии — 10$.

2ba6400634b24c979c9a29679de821fa.png

Настоятельно рекомендую пройти эти сессии, в спокойной обстановке, когда никто не отвлекает и не мешает, у меня была возможность только на выходных. Так же в эмуляторе есть возможность посмотреть правильные ответы, но я советую воспользоваться этой возможностью только в случае невозможности решить задачу самостоятельно.

Так как на экзамене можно использовать только несколько сторонних сайтов, как правило это документация к k8s, falco, etcd, то во время сессий я так же настоятельно советую открыть в веб проводнике https://kubernetes.io/docs/ и весь поиск производить только на самом сайте. Напоминаю, во время экзамена нельзя пользоваться поисковиками, даже если ссылка будет вести на разрешенный сайт. Это поможет привыкнуть к окружению, которое будет на реальном экзамене.

При подготовке практической части я использовал окружения от kodekloud, т.н. playgrounds

d89cdd8659df8d5bc299775281f4b21a.png25d933816fca0ff95511b79f5f400519.png

Ничего выдающегося, но экономит очень много времени и сил, когда вам надо быстро проверить какую то задачу.

Подготовка к экзамену

Ничем не отличается от CKA. Все тоже самое, как я описывал в первой статье.

Экзамен

Ничем не отличается от CKA, естественно кроме самих вопросов.

Tips & tricks

Поделюсь советами, которые помогут более эффективно сдать экзамен.

  1. Будьте особо внимательным к вопросам относительно изменений в kube apiserver и/или etcd. Если в результате ваших изменений вы получите не работающий kubeapi server, то все задачи, которые относились к этому кластеру будут считаться не решенными. Что приведет к большой потери баллов. Напомню, что проходной бал — 67%.

  2. Если вас просят запустить pod c определенным apparmor profile, то обращайте внимание на какой ноде необходимо производить запуск, так как профиль привязан к ноде.

    Если профиль необходимо применить, например, к deployment, то обращайте внимание в какой именно блок metadata вы добавляете соответствующую аннотацию. Аннотацию необходимо добавлять в spec.template.metadata.annotations

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    # неправильно
    container.apparmor.security.beta.kubernetes.io/nginx: localhost/deny-write
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
      annotations:
        # а так правильно
        container.apparmor.security.beta.kubernetes.io/nginx: localhost/deny-write
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

Так же не забываем, что в аннотации мы указываем имя контейнера, а не пода

  1. Если в задании требуется сохранить вывод в файл, то скорее всего это надо делать на student node (изначальная нода), и путь уже будет существовать, если такого пути нет, то скорее всего что-то делаете не то. Как вариант, вы забыли вернуться на изначальный хост. Аналогично и с ресурсами, если в задании сказано что ns уже создан, а вы видите что его нет, скорее всего вы забыли поменять контекст либо не вышли с master/worker node предыдущего кластера.

  2. Некоторые задания можно выполнять только на master/worker нодах, например там будут установлены kube-bench/trivy и т.п. рода утилиты. Обычно об этом явно говорится в задании, но не всегда. Например, если вам надо настроить аудит, то это можно сделать только на мастер ноде, но об этом не будут явно говорить. Для того чтобы быстро подключиться, делаем вывод нод k get node после смены контекста и затем ssh master-node-name или ssh worker-node-name

  3. Минимизируйте использование сторонних сайтов с документацией. Так как сама среда работает не особо быстро, а многие hot keys, например, поиск текста на странице не работают вообще, то поиск будет забирать у вас очень много времени, которого катастрофически не хватает.

    Если вас просят поменять или задать определенные параметры в kube apiserver или etcd. Используйте для этого уже существующие контейнеры, например, нас попросили установить минимальную версию tls в kube apiserver 1.3, то для этого достаточно выполнить такую команду

$ k exec -it -n kube-system kube-apiserver-controlplane -- kube-apiserver --help | grep tls-min
      --tls-min-version string                 Minimum TLS version supported. Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13

$ k exec -it -n kube-system kube-apiserver-controlplane -- kube-apiserver --help | grep cipher
      --tls-cipher-suites strings              Comma-separated list of cipher suites for the server. If omitted, the default Go cipher suites will be used. 

Мы сразу видим точное название параметра и возможные значения. Список шифров в случае с --tls-cipher-suitesвсегда указывается в задании. Перезагрузка etcd у меня занимала 2–3 минуты, следует это учитывать

$ k exec -it -n kube-system etcd-controlplane -- etcd --help | grep cipher
  --cipher-suites ''
    Comma-separated list of supported TLS cipher suites between client/server and peers (empty will be auto-populated by Go).
  1. Сэкономить еще немного времени так же поможет kubectl explainНапример, вас попросили добавить readOnlyRootFilesystem, но вы не помните точного написание и где именно надо указывать — используйте kubectl explain в сочетании с ключом --recursive=true

$ k explain pod.spec.containers --recursive=true | grep -i rootfilesystem -C10
   resources    
      limits    
      requests  
   securityContext      
      allowPrivilegeEscalation  
      capabilities      
         add    <[]string>
         drop   <[]string>
      privileged        
      procMount 
      readOnlyRootFilesystem    
      runAsGroup        
      runAsNonRoot      
      runAsUser 
      seLinuxOptions    
         level  
         role   
         type   
         user   
      seccompProfile    
         localhostProfile       

  1. Задания относящиеся к falco, часто могут быть решены с помощью sysdig. Например ваc просят сохранить логи в определенном формате для определенного контейнера в определенный файл. Если настраивать falco, то это потребует много времени, в отличие от sysdig

$ sysdig -M120 -p "%evt.time, %user.name %proc.name" container.id=abcdef123

И мы снова можем сэкономить время, не обращаюсь к документации falco, если вы не помните имя переменной

$ sysdig --list | grep time
$ sysdig --list | grep container
$ sysdig --list | grep proc

Так же в моем случае sysdig работал только с фильтром container.name, а с container.id ничего не выдавал

  1. В задании c ImagePolicyWebhook вам предлагают для проверки корректности настройки файл с ресурсом, в моем случае это был ReplicationController, который немного сбивает с толку, по крайней мере меня. Так как по условию вам говорится, что поды не должны создаваться, но при этом сам ReplicationController создается успешно. Первый раз меня это сбило с толку и я потратил лишние минут 5 на перепроверку всех параметров, затем просто создал pod c тегом latest и увидел в терминале, что мой запрос был заблокирован

  2. В заданиях с сетевыми политиками не забывайте про явную необходимость указывать namespace, если вас просят предоставить доступ к поду с любого namespace

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-app-label
  namespace: db
spec:
  podSelector:
    matchLabels:
      type: db
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          type: app

Таким образом мы разрешили входящий трафик в namespace=db для подов из любого namespace c меткой type=app

Так же обратите внимание на следующие примеры

  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: frontend
      podSelector:
        matchLabels:
          type: nodejs

  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: frontend
    - podSelector:
        matchLabels:
          type: nodejs

у этих правил будет абсолютно разный эффект, хотя отличие всего в один символ.

В первом случае мы разрешаем доступ только подам с меткой type=nodejs и только с namespace=frontend

Во втором случае мы разрешаем доступ любым подам с namespace=frontend

После создание сетевой политики рекомендую смотреть ее текстовое описание через describe

© Habrahabr.ru