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 Pod
Secret
—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: world
Typically 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 ConfigMap
s and Secret
s 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: localhost
hosts: 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=web
test
, web
and test-web
ansible_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!
Secret
s in environment variablesSecret
resource to store secret environment variablesenvFrom
if you then want to include all the secrets from that resourceSecret
s 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
moduledefinition
s, 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 ConfigMap
s (likely 2.8)Scenario:
ConfigMap
s?ConfigMap
used in a Deployment
will not update the Pod
s in that Deployment
Pod
s to pick up the ConfigMap
or Secret
s changeskubectl rollout undo
for emergency purposes will only roll back containers, not configurationConfigMap
sConfigMap
s based on a hash of its dataConfigMap
name in a Deployment
ConfigMap
will change its name, triggering Pod
updatesDeployment
will then roll back to the old configappend_hash
to generate immutable ConfigMaps
k8s_config_resource_name
filter plugin to reference such ConfigMap
sappend_hash
will enable immutable ConfigMap
s and Secret
s (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