registry/deploy/pkg/k8s/cert_manager.go
adam jones fe52766676
deploy: Deploy the registry to GCP (#255)
Adds the Pulumi code to:
- Deploy the registry (and associated services e.g. mongodb) to Google
Cloud Platform (GCP), on top of Google Kubernetes Engine (GKE)
- Sets up proper environments and secrets management
- Uses the real container image, now that it's published in #225. At the
moment attached to latest, we might want to pin the version later (or
perhaps always use `latest` in staging, and pin prod)
- Uses real domains (`staging.registry.modelcontextprotocol.io`) rather
than examples (``)

## Motivation and Context

Setting up infrastructure to deploy it. I set something up in Azure in
#227, although not super robust (e.g. no service accounts etc.). Think
we will use GCP as:
- the maintainers have experience with GCP, but none with Azure
- costs are quite low, and Anthropic is happy to cover them in the short
term
- means we only have to maintain one login system (just Google Cloud
Identity), not two (Google Workspace + Azure)

## How Has This Been Tested?

Deployed this to a staging and production cluster. Try it yourself at:

```bash
curl -H "Host: staging.registry.modelcontextprotocol.io" -k https://35.222.36.75/v0/ping
```

(will be sorting out domains very soon)

## Breaking Changes

NA - just adds support for GCP deployment

## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update

## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [x] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [x] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [x] I have added appropriate error handling
- [x] I have added or updated documentation as needed

## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->

Expected follow-ups:
- GitHub Action setup to deploy things to the cluster from GitHub, to
avoid gatekeeping to just the people with the secrets.
2025-08-12 17:44:50 +01:00

78 lines
2.4 KiB
Go

package k8s
import (
"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes"
"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/apiextensions"
v1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/core/v1"
"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/helm/v3"
metav1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/meta/v1"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"github.com/modelcontextprotocol/registry/deploy/infra/pkg/providers"
)
// SetupCertManager sets up cert-manager for TLS certificates
func SetupCertManager(ctx *pulumi.Context, cluster *providers.ProviderInfo) error {
// Create namespace for cert-manager
_, err := v1.NewNamespace(ctx, "cert-manager", &v1.NamespaceArgs{
Metadata: &metav1.ObjectMetaArgs{
Name: pulumi.String("cert-manager"),
},
}, pulumi.Provider(cluster.Provider))
if err != nil {
return err
}
// Install cert-manager for TLS certificates
_, err = helm.NewChart(ctx, "cert-manager", helm.ChartArgs{
Chart: pulumi.String("cert-manager"),
Version: pulumi.String("v1.18.2"),
FetchArgs: helm.FetchArgs{
Repo: pulumi.String("https://charts.jetstack.io"),
},
Namespace: pulumi.String("cert-manager"),
Values: pulumi.Map{
"installCRDs": pulumi.Bool(true),
"ingressShim": pulumi.Map{
"defaultIssuerName": pulumi.String("letsencrypt-prod"),
"defaultIssuerKind": pulumi.String("ClusterIssuer"),
},
},
}, pulumi.Provider(cluster.Provider))
if err != nil {
return err
}
_, err = apiextensions.NewCustomResource(ctx, "letsencrypt-prod", &apiextensions.CustomResourceArgs{
ApiVersion: pulumi.String("cert-manager.io/v1"),
Kind: pulumi.String("ClusterIssuer"),
Metadata: &metav1.ObjectMetaArgs{
Name: pulumi.String("letsencrypt-prod"),
},
OtherFields: kubernetes.UntypedArgs{
"spec": pulumi.Map{
"acme": pulumi.Map{
"server": pulumi.String("https://acme-v02.api.letsencrypt.org/directory"),
"email": pulumi.String("admin@modelcontextprotocol.io"),
"privateKeySecretRef": pulumi.Map{
"name": pulumi.String("letsencrypt-prod-key"),
},
"solvers": pulumi.Array{
pulumi.Map{
"http01": pulumi.Map{
"ingress": pulumi.Map{
"ingressClassName": pulumi.String("nginx"),
},
},
},
},
},
},
},
}, pulumi.Provider(cluster.Provider))
if err != nil {
return err
}
return nil
}