I saw a post by Michael Dehaan about a new configuration management system and thought “here we go, just what the world needs, yet another CM”
I was working at a banking/insurance company with locked down application servers with no root access or agents allowed. I had ssh and python though…
My first commit was July 2012—so some time around then
Mostly Kubernetes these days! But AWS works pretty well too
Starts now!
ansible-playbook playbooks/eks.yml -vv -e @overrides.yml -e env=test
Kubernetes allows the specification of common characteristics of applications and services:
Pod)Deployment/DaemonSet)Service)Service (Ingress)ConfigMap—one or more configuration items in key-value form. Useful for setting environment variables or specifying the entire contents of one or more files for a PodSecret—similar to ConfigMap but better protected from casual viewResource definitions are in YAML form
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config-map
namespace: my-namespace
data:
hello: worldTypically managed by the kubectl command line tool kubectl apply -f resource.yml
kubectl is awesome†Using Ansible’s shell and command modules properly: http://willthames.github.io/2016/09/21/using-command-and-shell-in-ansible.html
kubectl does validation of resource definitions against their specificationkubectl can append hashes to ConfigMaps and Secrets to make them immutablead-hoc tasks:
kubectl get configmap -n some-namespace some-config-map
ansible -m k8s_facts -a 'namespace=some-namespace kind=ConfigMap \
api_version=v1 name=some-config-map' localhost
{{ kube_resource_name }} {{ kube_ingress_fqdn }} across all applicationsAvoid control structures where possible
replicas = {% 5 if env == 'prod' else 1 %}
vs
replicas = {{ kube_deployment_replicas }}Sometimes whole sections of manifests differ between environment
metadata:
annotations:
{{ kube_ingress_annotations | to_nice_yaml(indent=2) | indent(4) }}
hosts: localhosthosts: localhost to talk to KubernetesMaking the most of Inventory: http://willthames.github.io/2017/10/31/making-the-most-of-inventory.html
hosts: "{{ env }}-{{ app }}-runner" with e.g. -e env=test -e app=webtest, web and test-webansible_connection: local and ansible_python_interpreter: "{{ ansible_playbook_python }}" in the runner group_vars fileGroup combinations explode as applications and environments increase
It’s easy to get this wrong with standard hosts files
generator inventory plugin generates such group combinations from a list of layers
[test:children]
test-web
test-api
[api:children]
test-api
[web:children]
test-web
[test-web]
test-web-runner
[test-api]
test-api-runner
[runner]
test-web-runner
test-api-runner
# inventory.config file in YAML format
plugin: generator
strict: False
hosts:
name: "{{ environment }}-{{ application }}-runner"
parents:
- name: "{{ environment }}-{{ application }}"
parents:
- name: "{{ application }}"
vars:
application: "{{ application }}"
- name: "{{ environment }}"
vars:
environment: "{{ environment }}"
- name: runner
layers:
environment:
- test
application:
- web
- api
ansible-vault for all of our secretsno_log with the k8s module when uploading secretsansible-vault encrypt_string to encrypt each secret inline
echo -n $secret | ansible-vault encrypt_string to avoid encrypting the newline!
Secrets in environment variablesSecret resource to store secret environment variablesenvFrom if you then want to include all the secrets from that resourceSecrets in environment variableskey1: !vault |
$ANSIBLE_VAULT;1.1;AES256
61666162663666643939353165393833383331313664616234343739653937336337626263663538
3335336263303963623332666639666364356166393462370a396465393637363938656562393936
61663834376235613564303237313131396335303336636466326430353530613836356564343832
6638393533663931640a663438313461616436393365346566313037613034323738646234363534
3734
my_secret_env:
KEY1: "{{ key1 | b64encode }}"
Secret manifestapiVersion: v1
kind: Secret
metadata:
name: my-secret-env
namespace: my-namespace
data:
{{ my_secret_env | to_nice_yaml(indent=2) | indent(2) }}
Secret---
kind: Deployment
spec:
template:
spec:
containers:
- envFrom:
- secretRef:
name: my-secret-env
k8s—main module for managing Kubernetes resourcesk8s_facts—useful for run-time querying of resourcesaws_eks_cluster—manages AWS EKS clustersazure_rm_aks—manages Azure Kubernetes Service clustersgcp_container_cluster and gcp_container_nodepool—manage GKE clusters and node poolsk8s moduledefinitions, or src from filetemplate lookup definition: "{{ lookup('template', 'path/to/resource.j2') | from_yaml }}"loop over a list of resourcesyaml stdout callback plugin is great for having output match inputk8s lookup plugin returns information about Kubernetes resourcesfrom_yaml and from_yaml_all (2.7) read from templates into module datab64encode encodes secrets in base64k8s_config_hash and k8s_config_resource_name for immutable ConfigMaps (likely 2.8)Scenario:
ConfigMaps?ConfigMap used in a Deployment will not update the Pods in that DeploymentPods to pick up the ConfigMap or Secrets changeskubectl rollout undo for emergency purposes will only roll back containers, not configurationConfigMapsConfigMaps based on a hash of its dataConfigMap name in a DeploymentConfigMap will change its name, triggering Pod updatesDeployment will then roll back to the old configappend_hash to generate immutable ConfigMapsk8s_config_resource_name filter plugin to reference such ConfigMapsappend_hash will enable immutable ConfigMaps and Secrets (likely 2.8)validate will return helpful warning and/or error messages if a resource manifest does not match the Kubernetes resource specification (likely 2.8)wait will allow you to wait until the Kubernetes resources are actually in the desired state (hopefully 2.8)Using Updated Modules with Stable Ansible: http://willthames.github.io/2017/12/12/using-updated-modules-with-stable-ansible.html