Skip to content

Commit

Permalink
Merge pull request #1 from castai/service-init
Browse files Browse the repository at this point in the history
Init service PoC
  • Loading branch information
Tsonov authored Aug 27, 2024
2 parents 031520c + f53f02c commit dab0e64
Show file tree
Hide file tree
Showing 22 changed files with 1,185 additions and 198 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*.dll
*.so
*.dylib
bin/

# Test binary, built with `go test -c`
*.test
Expand All @@ -23,3 +24,6 @@ go.work.sum

# env file
.env

# goland
.idea
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM gcr.io/distroless/static-debian11

#FROM ubuntu:latest
# TODO: Multi-arch build

COPY bin/castai-cloud-proxy-amd64 /usr/local/bin/castai-cloud-proxy
CMD ["castai-cloud-proxy"]
23 changes: 23 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
VERSION ?= poc2
REPO ?= lachezarcast/cloud-proxy

build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o bin/castai-cloud-proxy-amd64 ./cmd/proxy
#docker build -t us-docker.pkg.dev/castai-hub/library/svc:$(VERSION) .
docker build -t $(REPO):$(VERSION) --platform linux/amd64 .

push:
docker push $(REPO):$(VERSION)

release: build push

deploy: build push
# Get the latest digest because it doesn't work for some f. reason and put it in the yaml
@DIGEST=$$(docker inspect --format='{{index .RepoDigests 0}}' $(REPO):$(VERSION) | awk -F@ '{print $$2}'); \
sed "s/{{IMAGE_DIGEST}}/$${DIGEST}/g" dummy_deploy.yaml > tmp.yaml
kubectl apply -f tmp.yaml
rm tmp.yaml


generate-grpc:
protoc --go_out=./internal/castai/proto --go-grpc_out=./internal/castai/proto ./internal/castai/proto/proxy.proto
53 changes: 52 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,52 @@
# cloud-proxy
# cloud-proxy


## Running the PoC

PoC has two modes - a "local-only" test and a "mocked CAST" test so far. They are controlled via command-line args, see `cmd/proxy/main.go`.

The local-only test is good to debug issues with the "replace-credentials" part or workload identity (e.g. does my identity have access?).

The "mocked CAST" test is useful to simulate the flow running real GRPC connection, albeit local.

`make deploy` can be used to build, push an image and deploy the test proxy in the cluster kubectx points to currently.
You will have to provide the REPO and VERSION variables as defaults are specific to one developer right now :)

Easiest way to change modes is to edit dummy_deploy.yaml and redeploy.

## Enabling workload identity

The [GCP guide](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity) is OK.

Essential steps are:
- Create a GKE cluster and enable workload identity in settings
- If using existing cluster, update the cluster to use workload identity AND node pools to have GKE metadata server (restarts the nodes)
- Create a SA in k8s (one is provided in dummy_deploy.yaml)
- Grant the SA IAM permissions (or test without them first to see that they are required)

To grant IAM permissions to the service account:

Use the following to get the current project number:
```bash
gcloud projects list \
--filter="$(gcloud config get-value project)" \
--format="value(PROJECT_NUMBER)"
```

```bash
PROJECT_ID=XXX PROJECT_NUMBER=YYYY gcloud projects add-iam-policy-binding projects/$PROJECT_ID \
--role=roles/container.clusterViewer \
--member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/$PROJECT_ID.svc.id.goog/subject/ns/default/sa/castai-cloud-proxy \
--condition=None
```

**For some reason, above can fail with 404; no time to find out why now.**
Just replace the values in this command manually and it will work:

```bash
gcloud projects add-iam-policy-binding projects/<PROJECT_ID> \
--role=roles/container.clusterViewer \
--member=principal://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/<PROJECT_NUMBER>.svc.id.goog/subject/ns/default/sa/castai-cloud-proxy \
--condition=None
```

77 changes: 76 additions & 1 deletion cmd/proxy/main.go
Original file line number Diff line number Diff line change
@@ -1 +1,76 @@
package proxy
package main

import (
"flag"
"log"
"net/http"
"os"
"time"

"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

"github.com/castai/cloud-proxy/internal/castai/dummy"
"github.com/castai/cloud-proxy/internal/gcpauth"
"github.com/castai/cloud-proxy/internal/localtest"
"github.com/castai/cloud-proxy/internal/proxy"
)

const (
// TODO: Change accordingly for local testing

projectID = "engineering-test-353509"
location = "europe-north1-a"
testCluster = "lachezar-2708"
)

var (
runSanityTests = flag.Bool("sanity-checks", false, "run sanity checks that validate auth loading and basic executor function")
runMockCastTest = flag.Bool("mockcast", true, "run a test using a mock Cast.AI server")
)

func main() {
flag.Parse()

if runSanityTests != nil && *runSanityTests {
log.Println("run sanity tests is true, starting")
go func() {
localtest.RunBasicTests(projectID, location, testCluster)
localtest.RunProxyTest(projectID, location, testCluster)
}()
}

if runMockCastTest != nil && *runMockCastTest {
log.Println("run mockcast tests is true, starting")
go func() {
log.Println("Starting mock cast instance")
mockCast := &dummy.MockCast{}
if err := mockCast.Run(); err != nil {
log.Panicln("Error running mock Cast:", err)
}
}()

go func() {
loggerClientProxy := log.New(os.Stderr, "[CLUSTER PROXY] ", log.LstdFlags)
loggerClientProxy.Println("Starting proxy client")
conn, err := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
loggerClientProxy.Panicf("Failed to connect to server: %v", err)
}
defer func(conn *grpc.ClientConn) {
err := conn.Close()
if err != nil {
loggerClientProxy.Panicf("Failed to close gRPC connection: %v", err)
}
}(conn)

src := gcpauth.GCPCredentialsSource{}
executor := proxy.NewExecutor(src, http.DefaultClient)
client := proxy.NewClient(executor, loggerClientProxy)
client.Run(conn)
}()
}

log.Println("Sleeping for 1h, feel free to kill me")
time.Sleep(1 * time.Hour)
}
38 changes: 38 additions & 0 deletions dummy_deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloud-proxy-deployment
labels:
app: cloud-proxy
spec:
replicas: 1
selector:
matchLabels:
app: cloud-proxy
template:
metadata:
labels:
app: cloud-proxy
spec:
serviceAccountName: castai-cloud-proxy
containers:
- name: cloud-proxy-container
image: docker.io/lachezarcast/cloud-proxy@{{IMAGE_DIGEST}}
resources:
requests:
memory: "10Mi"
cpu: "50m"
limits:
memory: "10Mi"
imagePullPolicy: Always
command:
- "castai-cloud-proxy"
args:
- "-sanity-checks=false"
- "-mockcast=true"
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: castai-cloud-proxy
namespace: default
39 changes: 39 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module github.com/castai/cloud-proxy

go 1.22

require (
cloud.google.com/go/container v1.39.0
github.com/google/uuid v1.6.0
github.com/googleapis/gax-go/v2 v2.13.0
golang.org/x/oauth2 v0.22.0
google.golang.org/api v0.193.0
google.golang.org/grpc v1.65.0
google.golang.org/protobuf v1.34.2
)

require (
cloud.google.com/go/auth v0.9.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
cloud.google.com/go/compute/metadata v0.5.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/s2a-go v0.1.8 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
go.opentelemetry.io/otel v1.28.0 // indirect
go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.opentelemetry.io/otel/trace v1.28.0 // indirect
golang.org/x/crypto v0.26.0 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.24.0 // indirect
golang.org/x/text v0.17.0 // indirect
golang.org/x/time v0.6.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
)
Loading

0 comments on commit dab0e64

Please sign in to comment.