generated from cotes2020/chirpy-starter
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
309 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,46 @@ | ||
--- | ||
layout: post | ||
title: TCP | ||
title: Socket, TCP, and etc | ||
date: 2024-10-06 23:12 -0700 | ||
categories: [network] | ||
tags: [network, tcp] | ||
--- | ||
|
||
## Keepalive | ||
## TCP | ||
|
||
### Keepalive | ||
|
||
<https://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/> | ||
|
||
## Socket in general | ||
|
||
The first newbie question when doing socket programming is how to tell a socket | ||
has received all bytes from the other party. If you do not handle it well, you | ||
may get stuck forever at `recv`. The python | ||
[Socket Programming HOWTO](https://docs.python.org/3/howto/sockets.html) | ||
summarizes this issue as the fundamental truth of sockets: | ||
|
||
> messages must either be fixed length (yuck), or be delimited (shrug), or | ||
> indicate how long they are (much better), or end by shutting down the | ||
> connection | ||
There are only 4 ways! Joash Xu illustrates the first three in his | ||
[blog](https://enzircle.com/handling-message-boundaries-in-socket-programming). | ||
For the last option, you can read Ivan Velichko's | ||
[blog](https://iximiuz.com/en/posts/writing-web-server-in-python-sockets/). | ||
Also, I want to mention that HTTP protocol uses both delimited method and | ||
length method. It uses `\r\n` to separate the title line and header lines. Then | ||
it uses content-length header to determine the size of data section. | ||
|
||
## Netlink socket | ||
|
||
The best tutorial online is from | ||
[Kevin He](https://www.linuxjournal.com/article/7356). | ||
|
||
> Side note: Kevin He built a company call Deepmotion. It sounds interesting. | ||
## Epoll | ||
|
||
TOD: read this https://gist.github.com/dtoma/564375673b354397efc5 This is | ||
almost the same implementation as Java's default | ||
[http server implementation](https://github.com/openjdk/jdk/blob/dc08216f0ef55970c96df43bcc86ebd5792d486e/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
--- | ||
layout: post | ||
title: Istio | ||
date: 2024-12-16 13:10 -0800 | ||
categories: [network] | ||
tags: [network, istio, envoy] | ||
--- | ||
|
||
## Pilot | ||
|
||
Pilot has two components: `pilot-agent` and `pilot-discovery`. If you have read | ||
my [Envoy notes](envoy.md), you know that the xDS protocol has two parts: proxy | ||
and management server. `pilot-agent` is the proxy part, and `pilot-discovery` | ||
is the management server part. | ||
|
||
### Pilot-agent | ||
|
||
It runs in the istio-proxy container. Ex below: | ||
|
||
``` | ||
/usr/local/bin/pilot-agent proxy sidecar --domain filebeat.svc.cluster.local --proxyLogLevel=warning --proxyComponentLogLevel=misc:error --log_output_level=default:info --concurrency 2 | ||
``` | ||
|
||
It is mainly responsible for managing envoy proxy sidecar. | ||
|
||
### Pilot-discovery | ||
|
||
It runs in `istiod` pod. Ex below: | ||
|
||
``` | ||
/usr/local/bin/pilot-discovery discovery --monitoringAddr=:15014 --log_output_level=default:info --domain cluster.local --keepaliveMaxServerConnectionAge 30m | ||
``` | ||
|
||
Pilot-discovery is responsible for reacting to k8s events, converting these | ||
events to xDS responses and sending them to pilot-agents. We use two examples | ||
to illustrate how this part works. | ||
|
||
**Example 1: When a new service is deployed in a k8s cluster** | ||
|
||
As you can imagine, pilot-discovery subscribes service create/update/delete | ||
events in a k8s cluster. When an event happens, pilot-discovery will update its | ||
internal service registry and push this change to all envoy proxies. | ||
|
||
How does this process work? The answer is Kubernetes controllers. The | ||
controllers for all types of resources inside Kubernetes such as namespace, | ||
node, service, pod and etc are defined in | ||
[this file](https://github.com/istio/istio/blob/3ea5695508654a77c4c1638134c0a8aca7e9996b/pilot/pkg/serviceregistry/kube/controller/controller.go#L203). | ||
Especially for services, it register a handler for service event: | ||
|
||
``` | ||
c.registerHandlers(c.serviceInformer, "Services", c.onServiceEvent, nil) | ||
``` | ||
|
||
Inside the handler, it calls `xdsUpdater` to push the change to remote Envoy | ||
proxies. | ||
|
||
**Example 2: What happens when setting service mesh across two k8s clusters** | ||
|
||
Istio is able to set up a service mesh across multiple k8s clusters. How is | ||
this possible? To set it up, | ||
[One step](https://istio.io/latest/docs/setup/install/multicluster/multi-primary/#enable-endpoint-discovery) | ||
of the installation process is to run below command: | ||
|
||
``` | ||
istioctl x create-remote-secret --context="${CTX_CLUSTER1}" --name=cluster1 | kubectl apply -f - --context="${CTX_CLUSTER2}" | ||
``` | ||
|
||
It generates a yaml file like following | ||
|
||
``` | ||
apiVersion: v1 | ||
kind: Secret | ||
metadata: | ||
annotations: | ||
networking.istio.io/cluster: cluster1 | ||
creationTimestamp: null | ||
labels: | ||
istio/multiCluster: "true" | ||
name: istio-remote-secret-cluster1 | ||
namespace: istio-system | ||
stringData: | ||
cluster1: | | ||
apiVersion: v1 | ||
clusters: | ||
- cluster: | ||
certificate-authority-data: <...> | ||
server: https://369A1EB0F8100069D5C96281F5BD706D.gr7.us-east-2.eks.amazonaws.com | ||
name: cluster1 | ||
contexts: | ||
- context: | ||
cluster: cluster1 | ||
user: cluster1 | ||
name: cluster1 | ||
current-context: cluster1 | ||
kind: Config | ||
preferences: {} | ||
users: | ||
- name: cluster1 | ||
user: | ||
token: <...> | ||
``` | ||
|
||
and then applies it to cluster2. Basically, cluster2 now has credentials to | ||
operate on cluster1. See | ||
[this code](https://github.com/istio/istio/blob/44de8ccfe4d25bb658fb8f1efec9da314db4bd8b/istioctl/pkg/multicluster/remote_secret.go#L86) | ||
for more details about how this command works. The secret creation event will | ||
be captured by `secretcontroller` because it listens all events on secrets with | ||
label | ||
[istio/multiCluster](https://github.com/istio/istio/blob/3fcff36ddc5e69ed20755c6385d44eb1a0e50505/pkg/kube/multicluster/secretcontroller.go#L50), | ||
which registers a set of `ClusterHandler`s to handle secret | ||
create/update/delete events. | ||
|
||
#### How to use pilot-discovery debug endpoints | ||
|
||
Pilot-discovery provides a set of | ||
[debug endpoints](https://github.com/istio/istio/blob/cf3b4fdcba365825a1754ce2dca7a32544d6dfbd/pilot/pkg/xds/debug.go#L147-L194). | ||
Here, we show some example use cases. | ||
|
||
**Get all connected istioy-proxy instances** | ||
|
||
This endpoint will return all pods that have istio-proxy injected. | ||
|
||
``` | ||
$ ke istiod-64fb77c48d-x8cjj -- curl localhost:15014/debug/connections | ||
{ | ||
"totalClients": 21, | ||
"clients": [ | ||
{ | ||
"connectionId": "sidecar~172.31.90.176~airflow-scheduler-7bc4cf9fb8-bnb4r.data~data.svc.cluster.local-65372", | ||
"connectedAt": "2022-12-30T07:56:30.843188241Z", | ||
"address": "172.31.90.176:45502", | ||
"watches": null | ||
}, | ||
... | ||
``` | ||
|
||
**Get Envoy config dump** | ||
|
||
Envoy admin API has an endpoint | ||
[GET /config_dump](https://www.envoyproxy.io/docs/envoy/latest/operations/admin#get--config_dump). | ||
Istio has a debug endpoint to forward request to this `config_dump` endpoint. | ||
|
||
``` | ||
ke istiod-64fb77c48d-x8cjj -- curl localhost:15014/debug/config_dump?proxyID=sidecar~172.31.90.176~airflow-scheduler-7bc4cf9fb8-bnb4r.data~data.svc.cluster.local-6537 | ||
``` | ||
|
||
The output is huge. Note the `proxyID` query parameter is required and it is | ||
the `connnectionID` above. | ||
|
||
**Get all services** | ||
|
||
``` | ||
$ ke istiod-64fb77c48d-x8cjj -- curl localhost:15014/debug/registryz | ||
[ | ||
{ | ||
"Attributes": { | ||
"ServiceRegistry": "Kubernetes", | ||
"Name": "airflow-datadog-cluster-agent-admission-controller", | ||
"Namespace": "data", | ||
"UID": "istio://data/services/airflow-datadog-cluster-agent-admission-controller", | ||
"ExportTo": null, | ||
"LabelSelectors": { | ||
"app": "airflow-datadog-cluster-agent" | ||
}, | ||
"ClusterExternalAddresses": null, | ||
"ClusterExternalPorts": null | ||
}, | ||
"ports": [ | ||
{ | ||
"port": 443, | ||
"protocol": "UnsupportedProtocol" | ||
} | ||
], | ||
"creationTime": "2022-11-23T05:46:05Z", | ||
"hostname": "airflow-datadog-cluster-agent-admission-controller.data.svc.cluster.local", | ||
"address": "10.100.94.238", | ||
"Mutex": {}, | ||
"cluster-vips": { | ||
"cluster1": "10.100.94.238" | ||
}, | ||
"Resolution": 0, | ||
"MeshExternal": false | ||
}, | ||
``` | ||
|
||
The `cluster-vips` displays the virtual IP of the service in the corresponding | ||
cluster. If you have the same service set up in two clusters and in the same | ||
namespace, the you will see two records in `cluster-vips`, and istio will | ||
round-robin requests to these two clusters, namely, this service is a | ||
cross-cluster service. | ||
|
||
#### How does injection work | ||
|
||
Istio installation will install a MutatingWebhookConfiguration | ||
`istio-sidecar-injector` See blow sample output. As you can see that istiod has | ||
an endpoint `/inject` does then injection work. | ||
|
||
``` | ||
$ k describe mutatingwebhookconfiguration istio-sidecar-injector | ||
... | ||
Service: | ||
Name: istiod | ||
Namespace: istio-system | ||
Path: /inject | ||
Port: 443 | ||
... | ||
``` | ||
|
||
Checkout | ||
[code](https://github.com/istio/istio/blob/c36c5a5d36d6f77eed830fc13875b10459bfe5d6/pkg/kube/inject/webhook.go#L157) | ||
for more details. | ||
|
||
## Useful commands | ||
|
||
- `istioctl version`: quickly get all running versions. | ||
|
||
## Envoy | ||
|
||
Envoy is a proxy solution. There are so many proxies in the market: nginx, | ||
haproxy, trafik and etc, but why Envoy stands out? It is because the xDS APIs, | ||
or a fancier name, xDS protocol. Envoy project incubated a protocol that allows | ||
dynamically changing proxy configurations using a channel between proxy and the | ||
management server. | ||
|
||
Alex Burnos has a | ||
[great article](https://medium.com/@aburnos/data-plane-control-plane-and-their-apis-explained-d0a3fa7291f3) | ||
talking about data plane, control plane and universal data plan API. Just to | ||
copy his explanation here: | ||
|
||
- data plane: proxies | ||
- control plane: management server | ||
- data plan API: the API for proxies and management server to talk to each | ||
other, i.e., xDS APIs. | ||
|
||
See Envoy's golang implementation of data-plane-api: | ||
https://github.com/envoyproxy/go-control-plane. |