# Репозиторий с конфигурациями приложений, которые деплоятся на кластера K8s ## Структура каталогов в репозитории ```bash ├── clusters # каталог содержащий директории с кластерами │ ├── k8s-avroid-office.prod.local # имя промышленного кластера │ │ └── namespaces # каталог с директориями namespace, создаваемых в кластере k8s │ │ ├── argocd # namespace для РУЧНОГО деплоя ArgoCD │ │ │ ├── argo-cd # ArgoCD │ │ │ ├── argocd-apps # мета-приложения ArgoCD Bootstrapping │ │ │ ├── argocd-namespace.yaml # манифест namespace │ │ │ └── README.md # порядок деплоя ArgoCD │ │ │ │ │ ├── example # пример namespace │ │ │ ├── <ПРИЛОЖЕНИЕ/СЕРВИС> │ │ │ └── example.yaml # манифест namespace │ │ │ │ │ ├── # namespace для ручного или автоматического деплоя ArgoCD │ │ │ ├── .rbac # манифесты различных политик или секретов │ │ │ ├── app1 # приложение 1 │ │ │ ├── app2 # приложение 2 │ │ │ ├── ... │ │ │ ├── appN # приложение N │ │ │ └── .yaml # манифест namespace │ │ │ │ │ ├── kube-prometheus-stack # отдельный namespace cо стеком kube-prometheus-stack для мониторинга всего кластера │ │ │ │ │ ├── jenkins-builds # отдельный namespace интеграции с промышленным Jenkins │ │ │ │ │ ├── huawei-csi # отдельный namespace для Huawei CSI для интеграции с СХД │ │ │ │ │ └── vault-infra # отдельный namespace для Bank Vault для интеграции HashiCorp Vault │ │ │ ├── ... # имя промышленного кластера │ │ │ └── <КЛАСТЕР_K8S_N> # имя промышленного кластера │ └── README.md # этот файл ``` ## ArgoCD. Автоматизация развёртывания сервисов ArgoCD настроен таким образом, что он смотрит на `master`-ветку этого репозитория и, в зависимости от инстанса, обрабатывает только файлы попадающие под вот такую маску: ```bash Обрабатываемые файлы: clusters/<КЛАСТЕР_K8S>/namespaces/*/argocd-apps-*.yaml Исключение: clusters/<КЛАСТЕР_K8S>/namespaces/{argocd/*,example/*,vault-infra/*} ``` ## Настройка внешних секретов из HashiCorp Vault с помощью Bank Vaults [Ссылка на офф. доку](https://bank-vaults.dev) Для создания vault injector нужно установить helm ```bash helm upgrade -n vault-infra --install --wait vault-secrets-webhook oci://ghcr.io/bank-vaults/helm-charts/vault-secrets-webhook ``` Далее создать роль секрет и рольбиндинг ```bash kubectl apply -f clusters/k8s-avroid-office.prod.local/namespaces/vault-infra/vault-secrets-webhook/vault-service-account.yaml kubectl apply -f clusters/k8s-avroid-office.prod.local/namespaces/vault-infra/vault-secrets-webhook/vault-cluster_role_binding.yaml kubectl apply -f clusters/k8s-avroid-office.prod.local/namespaces/vault-infra/vault-secrets-webhook/vault-secret.yaml ``` Настройка со стороны vault ```bash vault auth enable -path=avroid-office kubernetes TOKEN=$(kubectl get secret vault -n vault-infra -o jsonpath="{.data.token}" | base64 --decode) CA_CERT=$(kubectl get secret vault -n vault-infra -o jsonpath="{.data['ca\.crt']}" | base64 --decode) ISSUER=$(kubectl get --raw /.well-known/openid-configuration | jq '.issuer') K8S_CLUSTER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}') vault write auth/avroid-office/config \ kubernetes_host="${K8S_CLUSTER}" \ token_reviewer_jwt="${TOKEN}" \ kubernetes_ca_cert="${CA_CERT}" \ issuer="${ISSUER}" \ disable_local_ca_jwt="true" ``` Далее создаем app роль - на каждый namespace нужно создавать свою роль с одноименным названием. ```bash vault write auth/avroid-office/role/tavro-cloud-dev \ bound_service_account_names="*" \ bound_service_account_namespaces="tavro-cloud-dev" \ policies="prj-tavro-cloud-backend" \ ttl="24h" ``` policies - содержит список vault полиси, если нужно добавить новый, то просто добавляем и выполняем эту команду ВНИМАНИЕ: для нормальной работы должен быть создан service-account в каждом namespace для этого просто нужно выполнить ```bash # не забудь поменять в файле namespace свой cp clusters/k8s-avroid-office.prod.local/namespaces/vault-infra/vault-secrets-webhook/vault-service-account.yaml ./ # далее меняем в файле имя на свой namespace и запускаем kubectl apply -f vault-service-account.yaml ``` Простой пример для тестирования - в логах вы увидите свой секрет ```bash kubectl apply -f - <<"EOF" apiVersion: apps/v1 kind: Deployment metadata: name: vault-test namespace: sandbox spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: vault-test template: metadata: labels: app.kubernetes.io/name: vault-test annotations: vault.security.banzaicloud.io/vault-addr: "https://vault.avroid.tech" # внешний адрес vault vault.security.banzaicloud.io/vault-role: "sandbox" # роль из под которой будем ходить в vault vault.security.banzaicloud.io/vault-skip-verify: "false" # проверять сертификат или нет на стороне vault # vault.security.banzaicloud.io/vault-tls-secret: "vault-tls" # сертификат для vault если он самоподписанный # vault.security.banzaicloud.io/vault-agent: "false" # запускать агента который будет отслеживать изменения секрета vault.security.banzaicloud.io/vault-ct-configmap: vault-test-config # конфиг который будет обрабатывать consul template vault.security.banzaicloud.io/vault-path: "avroid-office" # название kubernetes аутентификации в vault vault.security.banzaicloud.io/run-as-user: "100" # пользователь нужен что бы прочитать vault токен (100 - consul template) spec: serviceAccountName: vault # имя сервиса аккаунта - должен быть в каждом namespace containers: - name: alpine image: alpine command: ["sh", "-c", "echo ${FOO} && echo ${FOO_1} && echo going to sleep... && sleep 10000"] resources: requests: cpu: 50m memory: 32Mi limits: cpu: 50m memory: 32Mi env: # вариант когда секрет будет в переменную окружения - name: FOO # переменная окружения куда попадет секрет value: vault:sandbox/data/k8s/vault-test#FOO # путь до секрета - name: FOO_1 # пример задания переменной окружения из секретв valueFrom: secretKeyRef: name: vault-test-secret key: FOO_1 --- # вариант когда секрет нужно поместить в файл конфигурации приложения apiVersion: v1 kind: ConfigMap metadata: name: vault-test-config # используется в аннотации vault.security.banzaicloud.io/vault-ct-configmap namespace: sandbox data: config.hcl: | vault { vault_agent_token_file = "/vault/.vault-token" retry { backoff = "1s" } } template { contents = <