kubecon2020
kubecon2020 copied to clipboard
#+TITLE: Tutorial: Building Secure & Decentralized Global Applications on Kubernetes with NATS
/KubeCon 2020: NATS Tutorial/
[[https://nats.io][NATS]] is a simple, secure and performant communications system for digital systems, services and devices. NATS is a hosted project in the Cloud Native Computing Foundation ([[https://cncf.io][CNCF]]). NATS has over [[https://nats.io/download/][30 client language implementations]], and the NATS Server can run on-premise, in the cloud, at the edge, and even on a Raspberry Pi. NATS can secure and simplify design and operation of modern distributed systems.
Learn how to build applications that span across more than one Kubernetes region by using a NATS based global communications network. In this talk, it will be covered how to setup a globally available NATS cluster using multiple Kubernetes regions using NATS gateways and leafnode connections, as well as how to create applications that take advantage of the NATS decentralized authorization model by showing how to implement a simple Slack-like clone that runs under your terminal.
You can watch the tutorial by clicking on the image below:
[[https://www.youtube.com/watch?v=kN-GbWRVFos][https://img.youtube.com/vi/kN-GbWRVFos/maxresdefault.jpg]]
- Checkout the repo
Follow along with this repo: https://github.com/wallyqs/kubecon2020
#+begin_src sh git clone https://github.com/wallyqs/kubecon2020 #+end_src
- Setup decentralized auth
** Installing NSC
#+begin_src curl -LO https://raw.githubusercontent.com/nats-io/nsc/master/install.sh less install.sh sh ./install.sh #+end_src
** Initialize NSC
#+begin_src sh curl -fSl https://nats-io.github.io/k8s/setup/nsc-setup.sh | sh #+end_src
** Inspect NSC objects
#+begin_src sh tree nsc/ | less nsc describe jwt -f nsc/accounts/nats/KO/KO.jwt #+end_src
** Creating the KUBECON account
- We need 3 users at least:
- Chat Credentials Requestor
- Credentials Provisioner
- Chat User :: Will be dynamically generated
#+begin_src sh nsc add account --name KUBECON nsc list accounts nsc describe jwt -f ./nsc/accounts/nats/KO/accounts/KUBECON/KUBECON.jwt #+end_src
** Add a new signing key for KUBECON account
This is needed to be able to create users dynamically by the credentials provisioner.
#+begin_src sh nsc generate nkey --account --store nsc edit account --sk ACUIKNKJIAPABWJSIJM4GFYLQLL7RUWEBI2BIZYUINPWV5432ZOAEDV4 nsc describe jwt -f ./nsc/accounts/nats/KO/accounts/KUBECON/KUBECON.jwt #+end_src
** Create user for the credentials provisioner
#+begin_src
nsc add user chat-access
-K $NKEYS_PATH/keys/A/AO/AAOEOFBQCJKEJ7XZLLSHKVCERH34OPZOIJMOUUVW7QKESQ2KT33JZDRI.nk
--allow-sub 'chat.req.access'
--allow-pubsub '_INBOX.>'
--allow-pubsub 'R'
--allow-pubsub 'R.>'
nsc describe jwt -f $NKEYS_PATH/creds/KO/KUBECON/chat-access.creds #+end_src
** Create user for the credentials request
#+begin_src
nsc add user chat-creds-request
-K $NKEYS_PATH/keys/A/AO/AAOEOFBQCJKEJ7XZLLSHKVCERH34OPZOIJMOUUVW7QKESQ2KT33JZDRI.nk
--allow-pub 'chat.req.access'
--allow-pubsub '_INBOX.>'
--allow-pubsub 'R'
--allow-pubsub 'R.>'
nsc describe jwt -f $NKEYS_PATH/creds/KO/KUBECON/chat-creds-request.creds #+end_src
** Confirm setup locally
Generate the NATS configuration.
#+begin_src sh :results output source .nsc.env nsc list accounts nsc generate config --mem-resolver --sys-account SYS nsc generate config --mem-resolver --sys-account SYS > conf/resolver.conf #+end_src
Start the NATS Server:
#+begin_src sh nats-server -c conf/resolver.conf #+end_src
Try to make a request:
#+begin_src nats-req -creds nsc/nkeys/creds/KO/KUBECON/chat-creds-request.creds chat.req.access example #+end_src
Create a mock responder:
#+begin_src sh nats-rply -creds nsc/nkeys/creds/KO/KUBECON/chat-access.creds chat.req.access example #+end_src
- Using the Chat Application
** Running the provisioner
#+begin_src
cd chat-access
go run main.go --acc $NSC_HOME/nats/KO/accounts/KUBECON/KUBECON.jwt
--sk $NKEYS_PATH/keys/A/AO/AAOEOFBQCJKEJ7XZLLSHKVCERH34OPZOIJMOUUVW7QKESQ2KT33JZDRI.nk
--creds $NKEYS_PATH/creds/KO/KUBECON/chat-access.creds
#+end_src
** Getting some credentials and starting the app
#+begin_src cd chat nats-req -creds nsc/nkeys/creds/KO/KUBECON/chat-creds-request.creds chat.req.access wallyqs 2> my.creds go build ./... ./chat -creds my.creds #+end_src
- Deploying to K8S: Infra setup
** Creating K8S clusters for NATS
You can find info here:
https://docs.nats.io/nats-on-kubernetes/super-cluster-on-digital-ocean
Let's create 3 clusters in Digital Ocean:
#+begin_src sh doctl kubernetes cluster create nats-k8s-sfo2 --count 3 --region sfo2 doctl kubernetes cluster create nats-k8s-sgp1 --count 3 --region sgp1 doctl kubernetes cluster create nats-k8s-ams3 --count 3 --region ams3 #+end_src
** Open up the firewall for the required ports
- 4222 is the client port
- 7422 is the port for leafnodes
- 7522 is the port for gateway connections (cluster of clusters)
#+begin_src sh
for firewall in doctl compute firewall list | tail -n 3 | awk '{print $1}'
; do
doctl compute firewall add-rules $firewall --inbound-rules protocol:tcp,ports:4222,address:0.0.0.0/0
doctl compute firewall add-rules $firewall --inbound-rules protocol:tcp,ports:7422,address:0.0.0.0/0
doctl compute firewall add-rules $firewall --inbound-rules protocol:tcp,ports:7522,address:0.0.0.0/0
done
#+end_src
- Deploying NATS to a K8S Cluster
** Add Helm NATS repos
#+begin_src
brew install helm
helm repo add nats https://nats-io.github.io/k8s/helm/charts/
helm repo update
#+end_src
** Upload the memory resolver with the NATS accounts
#+begin_src sh for ctx in do-ams3-nats-k8s-ams3 do-sfo2-nats-k8s-sfo2 do-sgp1-nats-k8s-sgp1; do kubectl --context $ctx create cm nats-accounts --from-file conf/resolver.conf
kubectl --context $ctx delete cm nats-accounts
done
#+end_src
** Configure gateway connections
Using explicit URL endpoints though we could use [[https://github.com/kubernetes-sigs/external-dns][external-dns]] instead for this:
#+begin_src sh :results output
for ctx in do-ams3-nats-k8s-ams3 do-sgp1-nats-k8s-sgp1 do-sfo2-nats-k8s-sfo2; do
echo " - name: $ctx"
echo " urls:"
for externalIP in kubectl --context $ctx get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="ExternalIP")].address}'
; do
echo " - nats://$externalIP:7522";
done
echo
done
#+end_src
#+begin_example - name: do-ams3-nats-k8s-ams3 urls: - nats://164.90.192.194:7522 - nats://164.90.192.226:7522 - nats://164.90.192.80:7522
- name: do-sgp1-nats-k8s-sgp1
urls:
- nats://188.166.236.158:7522
- nats://188.166.232.25:7522
- nats://188.166.236.155:7522
- name: do-sfo2-nats-k8s-sfo2
urls:
- nats://64.227.50.254:7522
- nats://64.227.54.26:7522
- nats://138.197.219.203:7522
#+end_example
** Super Cluster YAML
#+begin_src yaml :tangle conf/super-cluster.yaml nats: image: nats:alpine
Bind a host port from the host for each one of the pods.
externalAccess: true
logging: debug: false trace: false
cluster: enabled: true
auth: enabled: true
resolver: ############################ # # # Memory resolver settings # # # ############################## type: memory
#
# Use a configmap reference which will be mounted
# into the container.
#
configMap:
name: nats-accounts
key: resolver.conf
gateway: enabled: true
NOTE: defined via --set gateway.name="$ctx"
name: $ctx
gateways: - name: do-ams3-nats-k8s-ams3 urls: - nats://164.90.192.194:7522 - nats://164.90.192.226:7522 - nats://164.90.192.80:7522
- name: do-sgp1-nats-k8s-sgp1
urls:
- nats://188.166.236.158:7522
- nats://188.166.232.25:7522
- nats://188.166.236.155:7522
- name: do-sfo2-nats-k8s-sfo2
urls:
- nats://64.227.50.254:7522
- nats://64.227.54.26:7522
- nats://138.197.219.203:7522
natsbox:
enabled: true
#+end_src
#+begin_src sh for ctx in do-ams3-nats-k8s-ams3 do-sfo2-nats-k8s-sfo2 do-sgp1-nats-k8s-sgp1; do helm --kube-context $ctx install nats nats/nats -f conf/super-cluster.yaml --set gateway.name=$ctx
helm --kube-context $ctx delete nats
done #+end_src
** Confirm the setup
- Peek at the connect_urls and confirm that the routes are present.
#+begin_src telnet 188.166.232.25 4222 #+end_src
Try to make a request from SF:
#+begin_src nats-req -s 138.197.219.203 -creds nsc/nkeys/creds/KO/KUBECON/chat-creds-request.creds chat.req.access example #+end_src
Create a mock responder in AMS:
#+begin_src sh nats-rply -s 164.90.192.226 -creds nsc/nkeys/creds/KO/KUBECON/chat-access.creds chat.req.access example #+end_src
- Using the System account
#+begin_src sh
nats-sub -s 188.166.236.158 -creds ./nsc/nkeys/creds/KO/SYS/sys.creds '>'
#+end_src