Traffic Management with Istio (5): Deploy Custom Gateway and Manage Its Certificates with cert-manager

Generate a Signature Key Pair

# Generate a CA private key
$ docker run -it -v $(pwd):/export frapsoft/openssl genrsa -out /export/ca.key 2048
# Create a self signed Certificate, valid for 10yrs with the 'signing' option set
$ docker run -it -v $(pwd):/export frapsoft/openssl req -x509 -new -nodes -key /export/ca.key -subj "/CN=${COMMON_NAME}" -days 3650 -reqexts v3_req -extensions v3_ca -out /export/ca.crt

Save the Signature Key Pair as a Secret

kubectl create secret tls ca-key-pair \
--cert=ca.crt \
--key=ca.key \
--namespace=default

Prepare K8s + Istio Environment

Deploy Istio-init

Use Application Directory to Easily Deploy Istio cert-manager

Create an Issuer Referencing the Secret

kubectl apply -f - <<EOF
apiVersion: certmanager.k8s.io/v1alpha1
kind: Issuer
metadata:
name: ca-issuer
namespace: default
spec:
ca:
secretName: ca-key-pair
EOF

Obtain a Signed Certificate

kubectl apply -f - <<EOF
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
name: myexample-certificate
namespace: default
spec:
secretName: istio-myexample-customingressgateway-certs
issuerRef:
name: ca-issuer
# You can reference Issuers of the type ClusterIssuer. By default, this usage only applies to the Issuer of the namespace.
kind: Issuer
commonName: myexample.com
organization:
- MyExample CA
dnsNames:
- myexample.com
- www.myexample.com
EOF

Check the Certificate and Key

kubectl describe certificate myexample-certificate
Name: myexample-certificate
namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"certmanager.k8s.io/v1alpha1","kind":"Certificate","metadata":{"annotations":{},"name":"myexample-certificate","namespace":"...
API Version: certmanager.k8s.io/v1alpha1
Kind: Certificate
Metadata:
Creation Timestamp: 2019-01-14T08:38:20Z
Generation: 1
Resource Version: 19727
Self Link: /apis/certmanager.k8s.io/v1alpha1/namespaces/default/certificates/myexample-certificate
UID: bf47b776-17d7-11e9-bafe-00163e069e12
Spec:
Common Name: myexample.com
Dns Names:
myexample.com
www.myexample.com
Issuer Ref:
Kind: Issuer
Name: ca-issuer
Organization:
MyExample CA
Secret Name: istio-myexample-customingressgateway-certs
Status:
Conditions:
Last Transition Time: 2019-01-14T08:38:22Z
Message: Certificate issued successfully
Reason: CertIssued
Status: True
Type: Ready
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal IssueCert 80s cert-manager Issuing certificate...
Normal CertIssued 80s cert-manager Certificate issued successfully
kubectl get secret istio-myexample-customingressgateway-certs -oyaml

Deploy a Custom Gateway

Define Internal Services

events {
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/logs/nginx/access.log main
error_log /var/log/nginx/error.log warn;
server {
listen 80;
location / {
return 200 'Welcome to myexample.com! This is one custom Istio Ingress Gateway powered by cert-manager!' ;
add_header Content-Type text/plain;
}
}
}
kubectl create configmap myexample-nginx-configmap --from-file=nginx.conf=./myexample-nginx.conf
\kubectl label namespace bookinfo istio-injection=enabled
kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: myexampleapp
labels:
app: myexampleapp
spec:
ports:
- port: 80
protocol: TCP
selector:
app: myexampleapp
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myexampleapp
spec:
selector:
matchLabels:
app: myexampleapp
replicas: 1
template:
metadata:
labels:
app: myexampleapp
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: cloud-config
mountPath: /etc/config
readOnly: true
volumes:
- name: cloud-config
configMap:
name: myexample-nginx-configmap
EOF

Create a Custom Gateway Configuration Object

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
annotations:
name: istio-myexample-customingressgateway
namespace: default
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- '*.myexample.com'
port:
name: http
number: 80
protocol: HTTP
tls:
httpsRedirect: true
- hosts:
- '*.myexample.com'
port:
- name: https
number: 443
protocol: HTTPS
tls:
mode: SIMPLE
privateKey: /etc/istio/ingressgateway-certs/tls.key
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
EOF

Create a VirtualService

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: istio-myexample-customvirtualservice
spec:
hosts:
- "www.myexample.com"
gateways:
- istio-myexample-customingressgateway
http:
- route:
- destination:
host: myexampleapp
port:
number: 80
EOF

Access Services Using a Gateway

kubectl get svc -l istio=ingressgateway
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 172.19.12.75 106.14.48.121 80:31144/TCP,443:30441/TCP 11m
INGRESS_HOST=106.14.48.121
SECURE_INGRESS_PORT=443
kubectl exec -it -n default $(kubectl -n default get pods -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') -- ls -al /etc/istio/ingressgateway-certs
kubectl exec -i -n default $(kubectl get pod -l istio=ingressgateway -n default -o jsonpath='{.items[0].metadata.name}')  -- cat /etc/istio/ingressgateway-certs/tls.crt | openssl x509 -text -noout | grep 'Subject:'
Subject: O=MyExample CA, CN=myexample.com
kubectl exec -ti $(kubectl get po -l istio=ingressgateway -n default -o jsonpath={.items[0]..metadata.name}) -n default -- curl  127.0.0.1:15000/certs
{
"ca_cert": "",
"cert_chain": "Certificate Path: /etc/istio/ingressgateway-certs/tls.crt, Serial Number: c181438895a781c98759fb56b9cc1508, Days until Expiration: 364"
}
curl -k -HHost:www.myexample.com --resolve www.myexample.com:443:106.14.48.121  https://www.myexample.com

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store