Skip to content

Commit

Permalink
Merge pull request #1 from caktus/init-role
Browse files Browse the repository at this point in the history
Add Ansible role
  • Loading branch information
copelco authored Feb 28, 2020
2 parents 16975a1 + 33c95a5 commit 87d6258
Show file tree
Hide file tree
Showing 13 changed files with 9,067 additions and 1 deletion.
9 changes: 9 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# caktus.k8s-web-cluster


## Changes


### v0.0.1 on Feb 26, 2020

* Initial release
27 changes: 27 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Copyright (c) 2020, Caktus Consulting Group, LLC
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

* Neither the name of the Caktus Consulting Group, LLC nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
122 changes: 121 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,121 @@
# ansible-role-k8s-web-cluster
# caktus.k8s-web-cluster

An Ansible role to help configure Kubernetes clusters for web apps.


# License

This Ansible role is released under the BSD License. See the
[LICENSE](https://github.com/caktus/ansible-role-k8s-web-cluster/blob/master/LICENSE)
file for more details.

Development sponsored by [Caktus Consulting Group, LLC](http://www.caktusgroup.com/services>).


# Requirements

* ``pip install openshift kubernetes-validate``


# Installation

1. Add to your ``requirements.yaml``:


```yaml
---
# file: deploy/requirements.yaml

- src: https://github.com/caktus/ansible-role-k8s-web-cluster
version: init-role # TODO: remove
name: caktus.k8s-web-cluster
```
2. Add the role to your playbook:
```yaml
---
# file: deploy/deploy.yaml

- hosts: k8s
roles:
- role: caktus.k8s-web-cluster
```
3. Add role vars configuration:
```yaml

---
# ----------------------------------------------------------------------------
# caktus.k8s-web-cluster: Configure kubernetes cluster for web apps
# ----------------------------------------------------------------------------

k8s_cluster_type: <aws|gcp|azure|digitalocean>
k8s_context: <name of context from ~/.kube/config>
k8s_letsencrypt_email: <email to contact about expiring certs>
k8s_echotest_hostname: <test hostname assigned to your cluster ip, e.g. echotest.caktus-built.com>
```
4. Run ``deploy.yaml`` playbook:
```sh
ansible-playbook -l <host/group> deploy.yaml -vv
```


### Testing that Let's Encrypt is working

1. Find the hostname or IP of your load balancer.
2. Add a DNS record for ``k8s_echotest_hostname`` to
point to this hostname or IP address (switching the record type if needed).
3. Give the record a minute or two to propagate.
4. Add an echotest playbook:

```yaml
---
# file: echotest.yaml

- hosts: k8s
tasks:
- name: Install echo test server
import_role:
name: caktus.k8s-web-cluster
tasks_from: echotest
```
5. Run ``echotest.yaml`` playbook:
```sh
ansible-playbook -l <host/group> echotest.yaml -vv
```

6. Give the certificate a couple minutes to be generated and validated. While waiting,
you can watch the output of:

kubectl -n echoserver get pod

When the ``cm-acme-http-solver`` pod goes away, the certificate should be
validated. Now, navigate to ``k8s_echotest_hostname`` and ensure that you
have a valid certificate. If you don't, you want to follow the
[cert-manager troubleshooting](https://docs.cert-manager.io/en/latest/getting-started/troubleshooting.html)
steps in the documentation. But, be sure to reload a few times, and close the
browser tab and open a new one to make sure it's really broken, because
sometimes it takes a few minutes to go through and the browser gets stuck
with the temporary certificate.

7. You should see the ``*-tls`` secret in the **echoserver** namespace:

kubectl -n echoserver get secret
NAME TYPE DATA AGE
default-token-62pdt kubernetes.io/service-account-token 3 5m
echoserver-tls kubernetes.io/tls 3 5m

If not, you may need to re-create the ingress by deleteing and re-applying
it.

8. When you're done, delete the echotest resources from the cluster. Run:

```sh
ansible-playbook -l <host/group> echotest.yaml --extra-vars "k8s_echotest_state=absent" -vv
```
10 changes: 10 additions & 0 deletions defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
k8s_kubeconfig: ~/.kube/config
k8s_cluster_type: ''
k8s_context: ''

k8s_install_ingress_controller: yes
k8s_letsencrypt_email: ''

k8s_echotest_state: present
k8s_echotest_hostname: 'echotest.caktus-built.com'
k8s_echotest_letsencrypt_issuer: 'letsencrypt-staging'
7 changes: 7 additions & 0 deletions meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
galaxy_info:
author: Caktus Consulting Group, LLC
description: Configure kubernetes web app clusters
company: Caktus Consulting Group, LLC
license: BSD
dependencies: []
12 changes: 12 additions & 0 deletions tasks/echotest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---

- name: Install echotest
k8s:
context: "{{ k8s_context }}"
kubeconfig: "{{ k8s_kubeconfig }}"
state: "{{ k8s_echotest_state }}"
wait: yes
validate:
fail_on_error: yes
strict: yes
definition: "{{ lookup('template', 'echotest.yml') }}"
67 changes: 67 additions & 0 deletions tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---

# cert-manager install process adapted from:
# https://cert-manager.io/docs/installation/kubernetes/#installing-with-regular-manifests
- name: Create namespace for cert-manager
k8s:
context: "{{ k8s_context }}"
kubeconfig: "{{ k8s_kubeconfig }}"
wait: yes
validate:
fail_on_error: yes
strict: yes
definition:
apiVersion: v1
kind: Namespace
metadata:
name: cert-manager
register: cert_manager

- name: Temporarily disable validation for cert-manager namespace
k8s:
context: "{{ k8s_context }}"
kubeconfig: "{{ k8s_kubeconfig }}"
wait: yes
validate:
fail_on_error: yes
strict: yes
definition:
apiVersion: v1
kind: Namespace
metadata:
name: cert-manager
labels:
certmanager.k8s.io/disable-validation: "true"
when: cert_manager is changed

- name: Deploy cert-manager and Let's Encrypt
k8s:
context: "{{ k8s_context }}"
kubeconfig: "{{ k8s_kubeconfig }}"
wait: yes
# FIXME: cert-manager.yaml doesn't validate, so this is disabled for now.
# Maybe the next version will validate?
# validate:
# fail_on_error: yes
# strict: yes
definition: "{{ lookup('template', item) }}"
with_items:
- letsencrypt/cert-manager.yaml
- letsencrypt/issuers.yaml

# ingress-nginx installation process adapted from:
# https://kubernetes.github.io/ingress-nginx/deploy/#prerequisite-generic-deployment-command
- name: Deploy Nginx Ingress Controller
k8s:
context: "{{ k8s_context }}"
kubeconfig: "{{ k8s_kubeconfig }}"
wait: yes
validate:
fail_on_error: yes
strict: yes
definition: "{{ lookup('template', item) }}"
with_items:
- ingress-nginx/mandatory.yaml
- ingress-nginx/cloud-generic.yaml
- ingress-nginx/patch-configmap.yaml
when: k8s_install_ingress_controller
61 changes: 61 additions & 0 deletions templates/echotest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
apiVersion: v1
kind: Namespace
metadata:
name: echoserver
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echoserver
namespace: echoserver
spec:
replicas: 1
selector:
matchLabels:
app: echoserver
template:
metadata:
labels:
app: echoserver
spec:
containers:
- image: gcr.io/google_containers/echoserver:1.10
imagePullPolicy: Always
name: echoserver
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: echoserver
namespace: echoserver
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
selector:
app: echoserver
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: echoserver
namespace: echoserver
annotations:
kubernetes.io/ingress.class: "nginx"
certmanager.k8s.io/cluster-issuer: "{{ k8s_echotest_letsencrypt_issuer }}"
spec:
tls:
- hosts:
- "{{ k8s_echotest_hostname }}"
secretName: echoserver-tls
rules:
- host: "{{ k8s_echotest_hostname }}"
http:
paths:
- path: /
backend:
serviceName: echoserver
servicePort: 80
33 changes: 33 additions & 0 deletions templates/ingress-nginx/cloud-generic.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
kind: Service
apiVersion: v1
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
{% if k8s_cluster_type == "digitalocean" %}
annotations:
service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: "true"
{% elif k8s_cluster_type == "aws" %}
annotations:
# Enable PROXY protocol
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
# Ensure the ELB idle timeout is less than nginx keep-alive timeout. By default,
# NGINX keep-alive is set to 75s. If using WebSockets, the value will need to be
# increased to '3600' to avoid any potential issues.
service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "60"
{% endif %}
spec:
externalTrafficPolicy: Local
type: LoadBalancer
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
ports:
- name: http
port: 80
targetPort: http
- name: https
port: 443
targetPort: https
Loading

0 comments on commit 87d6258

Please sign in to comment.