----初始化项目
This commit is contained in:
142
istio/pom.xml
Normal file
142
istio/pom.xml
Normal file
@ -0,0 +1,142 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>nacos-istio</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>nacos-istio ${project.version}</name>
|
||||
<url>https://nacos.io</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>nacos-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>nacos-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>nacos-config</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>nacos-naming</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>nacos-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-netty-shaded</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-protobuf</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-stub</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.api.grpc</groupId>
|
||||
<artifactId>proto-google-common-protos</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.envoyproxy.controlplane</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>0.1.27</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
<build>
|
||||
<extensions>
|
||||
<extension>
|
||||
<groupId>kr.motd.maven</groupId>
|
||||
<artifactId>os-maven-plugin</artifactId>
|
||||
<version>1.5.0.Final</version>
|
||||
</extension>
|
||||
</extensions>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>com.alibaba.nacos.istio.IstioApp</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.xolstice.maven.plugins</groupId>
|
||||
<artifactId>protobuf-maven-plugin</artifactId>
|
||||
<version>0.6.1</version>
|
||||
<configuration>
|
||||
<pluginId>grpc-java</pluginId>
|
||||
<protocArtifact>com.google.protobuf:protoc:${protobuf-java.version}:exe:${os.detected.classifier}</protocArtifact>
|
||||
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${protoc-gen-grpc-java.version}:exe:${os.detected.classifier}</pluginArtifact>
|
||||
|
||||
<useArgumentFile>true</useArgumentFile>
|
||||
<checkStaleness>true</checkStaleness>
|
||||
<staleMillis>10000</staleMillis>
|
||||
|
||||
<protoSourceRoot>src/main/resources/proto</protoSourceRoot>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
<goal>compile-custom</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
36
istio/src/main/java/com/alibaba/nacos/istio/IstioApp.java
Normal file
36
istio/src/main/java/com/alibaba/nacos/istio/IstioApp.java
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
/**
|
||||
* Istio starter.
|
||||
*
|
||||
* @author nkorange
|
||||
* @since 1.1.4
|
||||
*/
|
||||
@EnableScheduling
|
||||
@SpringBootApplication
|
||||
public class IstioApp {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(IstioApp.class, args);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.api;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
public class ApiConstants {
|
||||
|
||||
/**
|
||||
* Default api prefix of any type of google protocol buffer.
|
||||
*/
|
||||
public static final String API_TYPE_PREFIX = "type.googleapis.com/";
|
||||
|
||||
/**
|
||||
* Istio crd type url for mcp over xds
|
||||
* TODO Support other Istio crd, such as gateway, vs, dr and so on.
|
||||
*/
|
||||
public static final String SERVICE_ENTRY_PROTO_PACKAGE = "networking.istio.io/v1alpha3/ServiceEntry";
|
||||
public static final String MESH_CONFIG_PROTO_PACKAGE = "core/v1alpha1/MeshConfig";
|
||||
|
||||
/**
|
||||
* Istio crd type url for mcp
|
||||
*/
|
||||
public static final String MCP_PREFIX = "istio/";
|
||||
public static final String SERVICE_ENTRY_COLLECTION = MCP_PREFIX + "networking/v1alpha3/serviceentries";
|
||||
|
||||
/**
|
||||
* Istio crd type url of api.
|
||||
*/
|
||||
public static final String MCP_RESOURCE_PROTO = API_TYPE_PREFIX + "istio.mcp.v1alpha1.Resource";
|
||||
public static final String SERVICE_ENTRY_PROTO = API_TYPE_PREFIX + "istio.networking.v1alpha3.ServiceEntry";
|
||||
|
||||
/**
|
||||
* Standard xds type url
|
||||
* TODO Support lds, rds and sds
|
||||
*/
|
||||
public static final String CLUSTER_TYPE = API_TYPE_PREFIX + "envoy.config.cluster.v3.Cluster";
|
||||
public static final String ENDPOINT_TYPE = API_TYPE_PREFIX + "envoy.config.endpoint.v3.ClusterLoadAssignment";
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.api;
|
||||
|
||||
import com.alibaba.nacos.istio.common.ResourceSnapshot;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This interface is used to generator mcp resources or xds data.
|
||||
*
|
||||
* @author special.fy
|
||||
*/
|
||||
public interface ApiGenerator<T> {
|
||||
|
||||
/**
|
||||
* Generate data based on resource snapshot.
|
||||
*
|
||||
* @param resourceSnapshot Resource snapshot
|
||||
* @return data
|
||||
*/
|
||||
List<T> generate(ResourceSnapshot resourceSnapshot);
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.api;
|
||||
|
||||
import com.alibaba.nacos.istio.mcp.EmptyMcpGenerator;
|
||||
import com.alibaba.nacos.istio.mcp.ServiceEntryMcpGenerator;
|
||||
import com.alibaba.nacos.istio.xds.EmptyXdsGenerator;
|
||||
import com.alibaba.nacos.istio.xds.ServiceEntryXdsGenerator;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.alibaba.nacos.istio.api.ApiConstants.*;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
@Component
|
||||
public class ApiGeneratorFactory {
|
||||
|
||||
private final Map<String, ApiGenerator<?>> apiGeneratorMap;
|
||||
|
||||
public ApiGeneratorFactory() {
|
||||
apiGeneratorMap = new HashMap<>(2);
|
||||
// mcp over xds
|
||||
apiGeneratorMap.put(SERVICE_ENTRY_PROTO_PACKAGE, ServiceEntryXdsGenerator.getInstance());
|
||||
// TODO Support other api generator
|
||||
|
||||
// mcp
|
||||
apiGeneratorMap.put(SERVICE_ENTRY_COLLECTION, ServiceEntryMcpGenerator.getInstance());
|
||||
}
|
||||
|
||||
public ApiGenerator<?> getApiGenerator(String typeUrl) {
|
||||
ApiGenerator<?> apiGenerator = apiGeneratorMap.get(typeUrl);
|
||||
return apiGenerator != null ? apiGenerator :
|
||||
(typeUrl.startsWith(MCP_PREFIX) ? EmptyMcpGenerator.getInstance() : EmptyXdsGenerator.getInstance());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.common;
|
||||
|
||||
import io.grpc.stub.StreamObserver;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* AbstractConnection maintains the life cycle of the connection.
|
||||
*
|
||||
* @author special.fy
|
||||
*/
|
||||
public abstract class AbstractConnection<MessageT> {
|
||||
|
||||
private static AtomicLong connectIdGenerator = new AtomicLong(0);
|
||||
|
||||
private String connectionId;
|
||||
|
||||
protected StreamObserver<MessageT> streamObserver;
|
||||
|
||||
private final Map<String, WatchedStatus> watchedResources;
|
||||
|
||||
public AbstractConnection(StreamObserver<MessageT> streamObserver) {
|
||||
this.streamObserver = streamObserver;
|
||||
this.watchedResources = new HashMap<>(1 << 4);
|
||||
}
|
||||
|
||||
public void setConnectionId(String clientId) {
|
||||
long id = connectIdGenerator.getAndIncrement();
|
||||
this.connectionId = clientId + "-" + id;
|
||||
}
|
||||
|
||||
public String getConnectionId() {
|
||||
return connectionId;
|
||||
}
|
||||
|
||||
public void addWatchedResource(String resourceType, WatchedStatus watchedStatus) {
|
||||
watchedResources.put(resourceType, watchedStatus);
|
||||
}
|
||||
|
||||
public WatchedStatus getWatchedStatusByType(String resourceType) {
|
||||
return watchedResources.get(resourceType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push data to grpc connection.
|
||||
*
|
||||
* @param message response
|
||||
* @param watchedStatus watched status
|
||||
*/
|
||||
public abstract void push(MessageT message, WatchedStatus watchedStatus);
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.common;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
public class Event {
|
||||
|
||||
public static final Event SERVICE_UPDATE_EVENT = new Event(EventType.Service);
|
||||
|
||||
private EventType type;
|
||||
|
||||
public Event(EventType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public EventType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(EventType type) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.common;
|
||||
|
||||
import com.alibaba.nacos.istio.mcp.NacosMcpService;
|
||||
import com.alibaba.nacos.istio.misc.Loggers;
|
||||
import com.alibaba.nacos.istio.util.IstioExecutor;
|
||||
import com.alibaba.nacos.istio.xds.NacosXdsService;
|
||||
import com.alibaba.nacos.sys.utils.ApplicationUtils;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* EventProcessor.
|
||||
*
|
||||
* @author special.fy
|
||||
*/
|
||||
@Component
|
||||
public class EventProcessor implements ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
private static final int MAX_WAIT_EVENT_TIME = 100;
|
||||
|
||||
private NacosMcpService nacosMcpService;
|
||||
|
||||
private NacosXdsService nacosXdsService;
|
||||
|
||||
private NacosResourceManager resourceManager;
|
||||
|
||||
private final BlockingQueue<Event> events;
|
||||
|
||||
public EventProcessor() {
|
||||
events = new ArrayBlockingQueue<>(20);
|
||||
}
|
||||
|
||||
/**
|
||||
* notify.
|
||||
*
|
||||
* @param event event
|
||||
*/
|
||||
public void notify(Event event) {
|
||||
try {
|
||||
events.put(event);
|
||||
} catch (InterruptedException e) {
|
||||
Loggers.MAIN.warn("There are too many events, this event {} will be ignored.", event.getType());
|
||||
// set the interrupted flag
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleEvents() {
|
||||
Consumer handleEvents = new Consumer("handle events");
|
||||
handleEvents.setDaemon(true);
|
||||
handleEvents.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
|
||||
if (contextRefreshedEvent.getApplicationContext().getParent() == null) {
|
||||
checkDependenceReady();
|
||||
handleEvents();
|
||||
}
|
||||
}
|
||||
|
||||
private class Consumer extends Thread {
|
||||
|
||||
Consumer(String name) {
|
||||
setName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("InfiniteLoopStatement")
|
||||
public void run() {
|
||||
Future<Void> task = null;
|
||||
boolean hasNewEvent = false;
|
||||
Event lastEvent = null;
|
||||
while (true) {
|
||||
try {
|
||||
// Today we only care about service event,
|
||||
// so we simply ignore event until the last task has been completed.
|
||||
Event event = events.poll(MAX_WAIT_EVENT_TIME, TimeUnit.MILLISECONDS);
|
||||
if (event != null) {
|
||||
hasNewEvent = true;
|
||||
lastEvent = event;
|
||||
}
|
||||
if (hasClientConnection() && needNewTask(hasNewEvent, task)) {
|
||||
task = IstioExecutor.asyncHandleEvent(new EventHandleTask(lastEvent));
|
||||
hasNewEvent = false;
|
||||
lastEvent = null;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Loggers.MAIN.warn("Thread {} is be interrupted.", getName());
|
||||
// set the interrupted flag
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasClientConnection() {
|
||||
return nacosMcpService.hasClientConnection() || nacosXdsService.hasClientConnection();
|
||||
}
|
||||
|
||||
private boolean needNewTask(boolean hasNewEvent, Future<Void> task) {
|
||||
return hasNewEvent && (task == null || task.isDone());
|
||||
}
|
||||
|
||||
private class EventHandleTask implements Callable<Void> {
|
||||
|
||||
private final Event event;
|
||||
|
||||
EventHandleTask(Event event) {
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
ResourceSnapshot snapshot = resourceManager.createResourceSnapshot();
|
||||
nacosXdsService.handleEvent(snapshot, event);
|
||||
nacosMcpService.handleEvent(snapshot, event);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkDependenceReady() {
|
||||
if (null == resourceManager) {
|
||||
resourceManager = ApplicationUtils.getBean(NacosResourceManager.class);
|
||||
}
|
||||
if (null == nacosXdsService) {
|
||||
nacosXdsService = ApplicationUtils.getBean(NacosXdsService.class);
|
||||
}
|
||||
if (null == nacosMcpService) {
|
||||
nacosMcpService = ApplicationUtils.getBean(NacosMcpService.class);
|
||||
}
|
||||
return Objects.nonNull(resourceManager) && Objects.nonNull(nacosMcpService) && Objects.nonNull(nacosXdsService);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.common;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
public enum EventType {
|
||||
|
||||
/**
|
||||
* The service info of nacos changes.
|
||||
*/
|
||||
Service,
|
||||
|
||||
/**
|
||||
* The endpoints of service change.
|
||||
*/
|
||||
Endpoint;
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.common;
|
||||
|
||||
import com.alibaba.nacos.istio.misc.IstioConfig;
|
||||
import com.alibaba.nacos.istio.model.IstioService;
|
||||
import com.alibaba.nacos.istio.util.IstioExecutor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
@Component
|
||||
public class NacosResourceManager {
|
||||
|
||||
private ResourceSnapshot resourceSnapshot;
|
||||
|
||||
@Autowired
|
||||
NacosServiceInfoResourceWatcher serviceInfoResourceWatcher;
|
||||
|
||||
@Autowired
|
||||
private IstioConfig istioConfig;
|
||||
|
||||
public NacosResourceManager() {
|
||||
resourceSnapshot = new ResourceSnapshot();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
IstioExecutor.registerNacosResourceWatcher(serviceInfoResourceWatcher, istioConfig.getMcpPushInterval() * 2L,
|
||||
istioConfig.getMcpPushInterval());
|
||||
}
|
||||
|
||||
public Map<String, IstioService> services() {
|
||||
return serviceInfoResourceWatcher.snapshot();
|
||||
}
|
||||
|
||||
public IstioConfig getIstioConfig() {
|
||||
return istioConfig;
|
||||
}
|
||||
|
||||
public synchronized ResourceSnapshot getResourceSnapshot() {
|
||||
return resourceSnapshot;
|
||||
}
|
||||
|
||||
public synchronized void setResourceSnapshot(ResourceSnapshot resourceSnapshot) {
|
||||
this.resourceSnapshot = resourceSnapshot;
|
||||
}
|
||||
|
||||
public void initResourceSnapshot() {
|
||||
ResourceSnapshot resourceSnapshot = getResourceSnapshot();
|
||||
resourceSnapshot.initResourceSnapshot(this);
|
||||
}
|
||||
|
||||
public ResourceSnapshot createResourceSnapshot() {
|
||||
ResourceSnapshot resourceSnapshot = new ResourceSnapshot();
|
||||
resourceSnapshot.initResourceSnapshot(this);
|
||||
setResourceSnapshot(resourceSnapshot);
|
||||
return resourceSnapshot;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.common;
|
||||
|
||||
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
|
||||
import com.alibaba.nacos.istio.model.IstioService;
|
||||
import com.alibaba.nacos.istio.util.IstioCrdUtil;
|
||||
import com.alibaba.nacos.naming.core.v2.ServiceManager;
|
||||
import com.alibaba.nacos.naming.core.v2.index.ServiceStorage;
|
||||
import com.alibaba.nacos.naming.core.v2.pojo.Service;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
@org.springframework.stereotype.Service
|
||||
public class NacosServiceInfoResourceWatcher implements Runnable {
|
||||
|
||||
private final Map<String, IstioService> serviceInfoMap = new ConcurrentHashMap<>(16);
|
||||
|
||||
@Autowired
|
||||
private ServiceStorage serviceStorage;
|
||||
|
||||
@Autowired
|
||||
private EventProcessor eventProcessor;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
boolean changed = false;
|
||||
|
||||
// Query all services to see if any of them have changes.
|
||||
Set<String> namespaces = ServiceManager.getInstance().getAllNamespaces();
|
||||
Set<String> allServices = new HashSet<>();
|
||||
for (String namespace : namespaces) {
|
||||
Set<Service> services = ServiceManager.getInstance().getSingletons(namespace);
|
||||
if (services.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Service service : services) {
|
||||
String serviceName = IstioCrdUtil.buildServiceNameForServiceEntry(service);
|
||||
allServices.add(serviceName);
|
||||
|
||||
IstioService old = serviceInfoMap.get(serviceName);
|
||||
// Service not changed
|
||||
if (old != null && old.getRevision().equals(service.getRevision())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Update the resource
|
||||
changed = true;
|
||||
ServiceInfo serviceInfo = serviceStorage.getPushData(service);
|
||||
if (!serviceInfo.isValid()) {
|
||||
serviceInfoMap.remove(serviceName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (old != null) {
|
||||
serviceInfoMap.put(serviceName, new IstioService(service, serviceInfo, old));
|
||||
} else {
|
||||
serviceInfoMap.put(serviceName, new IstioService(service, serviceInfo));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String key : serviceInfoMap.keySet()) {
|
||||
if (!allServices.contains(key)) {
|
||||
changed = true;
|
||||
serviceInfoMap.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
eventProcessor.notify(Event.SERVICE_UPDATE_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, IstioService> snapshot() {
|
||||
return new HashMap<>(serviceInfoMap);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.common;
|
||||
|
||||
import com.alibaba.nacos.istio.model.IstioService;
|
||||
import com.alibaba.nacos.istio.model.ServiceEntryWrapper;
|
||||
import com.alibaba.nacos.istio.util.IstioCrdUtil;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
public class ResourceSnapshot {
|
||||
private static AtomicLong versionSuffix = new AtomicLong(0);
|
||||
|
||||
private final List<ServiceEntryWrapper> serviceEntries;
|
||||
|
||||
private boolean isCompleted;
|
||||
|
||||
private String version;
|
||||
|
||||
public ResourceSnapshot() {
|
||||
isCompleted = false;
|
||||
serviceEntries = new ArrayList<>();
|
||||
}
|
||||
|
||||
public synchronized void initResourceSnapshot(NacosResourceManager manager) {
|
||||
if (isCompleted) {
|
||||
return;
|
||||
}
|
||||
|
||||
initServiceEntry(manager);
|
||||
|
||||
generateVersion();
|
||||
|
||||
isCompleted = true;
|
||||
}
|
||||
|
||||
private void generateVersion() {
|
||||
String time = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date());
|
||||
version = time + "/" + versionSuffix.getAndIncrement();
|
||||
}
|
||||
|
||||
private void initServiceEntry(NacosResourceManager manager) {
|
||||
Map<String, IstioService> serviceInfoMap = manager.services();
|
||||
for (String serviceName : serviceInfoMap.keySet()) {
|
||||
ServiceEntryWrapper serviceEntryWrapper = IstioCrdUtil.buildServiceEntry(serviceName, manager.getIstioConfig().getDomainSuffix(), serviceInfoMap.get(serviceName));
|
||||
if (serviceEntryWrapper != null) {
|
||||
serviceEntries.add(serviceEntryWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public List<ServiceEntryWrapper> getServiceEntries() {
|
||||
return serviceEntries;
|
||||
}
|
||||
|
||||
public boolean isCompleted() {
|
||||
return isCompleted;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.common;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
public class WatchedStatus {
|
||||
|
||||
private String type;
|
||||
|
||||
private String latestVersion;
|
||||
|
||||
private String latestNonce;
|
||||
|
||||
private String ackedVersion;
|
||||
|
||||
private String ackedNonce;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getLatestVersion() {
|
||||
return latestVersion;
|
||||
}
|
||||
|
||||
public void setLatestVersion(String latestVersion) {
|
||||
this.latestVersion = latestVersion;
|
||||
}
|
||||
|
||||
public String getLatestNonce() {
|
||||
return latestNonce;
|
||||
}
|
||||
|
||||
public void setLatestNonce(String latestNonce) {
|
||||
this.latestNonce = latestNonce;
|
||||
}
|
||||
|
||||
public String getAckedVersion() {
|
||||
return ackedVersion;
|
||||
}
|
||||
|
||||
public void setAckedVersion(String ackedVersion) {
|
||||
this.ackedVersion = ackedVersion;
|
||||
}
|
||||
|
||||
public String getAckedNonce() {
|
||||
return ackedNonce;
|
||||
}
|
||||
|
||||
public void setAckedNonce(String ackedNonce) {
|
||||
this.ackedNonce = ackedNonce;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.config;
|
||||
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.istio.IstioApp;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
import com.alibaba.nacos.sys.filter.NacosPackageExcludeFilter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import static com.alibaba.nacos.sys.env.EnvUtil.FUNCTION_MODE_NAMING;
|
||||
|
||||
/**
|
||||
* Istio module enabled filter by spring packages scan.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class IstioEnabledFilter implements NacosPackageExcludeFilter {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(IstioEnabledFilter.class);
|
||||
|
||||
private static final String ISTIO_ENABLED_KEY = "nacos.extension.naming.istio.enabled";
|
||||
|
||||
@Override
|
||||
public String getResponsiblePackagePrefix() {
|
||||
return IstioApp.class.getPackage().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExcluded(String className, Set<String> annotationNames) {
|
||||
String functionMode = EnvUtil.getFunctionMode();
|
||||
// When not specified naming mode or specified all mode, the naming module not start and load.
|
||||
if (isNamingDisabled(functionMode)) {
|
||||
LOGGER.warn("Istio module disabled because function mode is {}, and Istio depend naming module",
|
||||
functionMode);
|
||||
return true;
|
||||
}
|
||||
boolean istioDisabled = !EnvUtil.getProperty(ISTIO_ENABLED_KEY, Boolean.class, false);
|
||||
if (istioDisabled) {
|
||||
LOGGER.warn("Istio module disabled because set {} as false", ISTIO_ENABLED_KEY);
|
||||
}
|
||||
return istioDisabled;
|
||||
}
|
||||
|
||||
private boolean isNamingDisabled(String functionMode) {
|
||||
if (StringUtils.isEmpty(functionMode)) {
|
||||
return false;
|
||||
}
|
||||
return !FUNCTION_MODE_NAMING.equals(functionMode);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.mcp;
|
||||
|
||||
import com.alibaba.nacos.istio.api.ApiGenerator;
|
||||
import com.alibaba.nacos.istio.common.ResourceSnapshot;
|
||||
import istio.mcp.v1alpha1.ResourceOuterClass.Resource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
public class EmptyMcpGenerator implements ApiGenerator<Resource> {
|
||||
|
||||
private volatile static EmptyMcpGenerator singleton = null;
|
||||
|
||||
public static EmptyMcpGenerator getInstance() {
|
||||
if (singleton == null) {
|
||||
synchronized (EmptyMcpGenerator.class) {
|
||||
if (singleton == null) {
|
||||
singleton = new EmptyMcpGenerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
return singleton;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Resource> generate(ResourceSnapshot resourceSnapshot) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.mcp;
|
||||
|
||||
import com.alibaba.nacos.istio.common.AbstractConnection;
|
||||
import com.alibaba.nacos.istio.common.WatchedStatus;
|
||||
import com.alibaba.nacos.istio.misc.Loggers;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import istio.mcp.v1alpha1.Mcp;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
public class McpConnection extends AbstractConnection<Mcp.Resources> {
|
||||
|
||||
public McpConnection(StreamObserver<Mcp.Resources> streamObserver) {
|
||||
super(streamObserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void push(Mcp.Resources response, WatchedStatus watchedStatus) {
|
||||
if (Loggers.MAIN.isDebugEnabled()) {
|
||||
Loggers.MAIN.debug("Mcp.Resources: {}", response.toString());
|
||||
}
|
||||
|
||||
this.streamObserver.onNext(response);
|
||||
|
||||
// Update watched status
|
||||
watchedStatus.setLatestVersion(response.getSystemVersionInfo());
|
||||
watchedStatus.setLatestNonce(response.getNonce());
|
||||
|
||||
Loggers.MAIN.info("mcp: push, type: {}, connection-id {}, version {}, nonce {}, resource size {}.",
|
||||
watchedStatus.getType(),
|
||||
getConnectionId(),
|
||||
response.getSystemVersionInfo(),
|
||||
response.getNonce(),
|
||||
response.getResourcesCount());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.mcp;
|
||||
|
||||
import com.alibaba.nacos.istio.api.ApiGenerator;
|
||||
import com.alibaba.nacos.istio.api.ApiGeneratorFactory;
|
||||
import com.alibaba.nacos.istio.common.AbstractConnection;
|
||||
import com.alibaba.nacos.istio.common.Event;
|
||||
import com.alibaba.nacos.istio.common.NacosResourceManager;
|
||||
import com.alibaba.nacos.istio.common.ResourceSnapshot;
|
||||
import com.alibaba.nacos.istio.common.WatchedStatus;
|
||||
import com.alibaba.nacos.istio.misc.Loggers;
|
||||
import com.alibaba.nacos.istio.util.NonceGenerator;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import istio.mcp.v1alpha1.Mcp;
|
||||
import istio.mcp.v1alpha1.ResourceOuterClass.Resource;
|
||||
import istio.mcp.v1alpha1.ResourceSourceGrpc;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static com.alibaba.nacos.istio.api.ApiConstants.SERVICE_ENTRY_COLLECTION;
|
||||
|
||||
/**
|
||||
* nacos mcp service.
|
||||
*
|
||||
* @author nkorange
|
||||
* @since 1.1.4
|
||||
*/
|
||||
@Service
|
||||
public class NacosMcpService extends ResourceSourceGrpc.ResourceSourceImplBase {
|
||||
|
||||
private final Map<String, AbstractConnection<Mcp.Resources>> connections = new ConcurrentHashMap<>(16);
|
||||
|
||||
@Autowired
|
||||
ApiGeneratorFactory apiGeneratorFactory;
|
||||
|
||||
@Autowired
|
||||
NacosResourceManager resourceManager;
|
||||
|
||||
public boolean hasClientConnection() {
|
||||
return connections.size() != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StreamObserver<Mcp.RequestResources> establishResourceStream(StreamObserver<Mcp.Resources> responseObserver) {
|
||||
|
||||
// TODO add authN
|
||||
|
||||
// Init snapshot of nacos service info.
|
||||
resourceManager.initResourceSnapshot();
|
||||
AbstractConnection<Mcp.Resources> newConnection = new McpConnection(responseObserver);
|
||||
|
||||
return new StreamObserver<Mcp.RequestResources>() {
|
||||
private boolean initRequest = true;
|
||||
|
||||
@Override
|
||||
public void onNext(Mcp.RequestResources requestResources) {
|
||||
// init connection
|
||||
if (initRequest) {
|
||||
newConnection.setConnectionId(requestResources.getSinkNode().getId());
|
||||
connections.put(newConnection.getConnectionId(), newConnection);
|
||||
initRequest = false;
|
||||
}
|
||||
|
||||
process(requestResources, newConnection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable throwable) {
|
||||
Loggers.MAIN.error("mcp: {} stream error.", newConnection.getConnectionId(), throwable);
|
||||
clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
responseObserver.onCompleted();
|
||||
clear();
|
||||
}
|
||||
|
||||
private void clear() {
|
||||
connections.remove(newConnection.getConnectionId());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void process(Mcp.RequestResources requestResources, AbstractConnection<Mcp.Resources> connection) {
|
||||
if (!shouldPush(requestResources, connection)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Mcp.Resources response = buildMcpResourcesResponse(requestResources.getCollection(), resourceManager.getResourceSnapshot());
|
||||
connection.push(response, connection.getWatchedStatusByType(requestResources.getCollection()));
|
||||
}
|
||||
|
||||
private boolean shouldPush(Mcp.RequestResources requestResources, AbstractConnection<Mcp.Resources> connection) {
|
||||
String type = requestResources.getCollection();
|
||||
String connectionId = connection.getConnectionId();
|
||||
|
||||
if (requestResources.getErrorDetail().getCode() != 0) {
|
||||
Loggers.MAIN.error("mcp: ACK error, connection-id: {}, code: {}, message: {}",
|
||||
connectionId,
|
||||
requestResources.getErrorDetail().getCode(),
|
||||
requestResources.getErrorDetail().getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
WatchedStatus watchedStatus;
|
||||
if (requestResources.getResponseNonce().isEmpty()) {
|
||||
Loggers.MAIN.info("mcp: init request, type {}, connection-id {}, is incremental {}",
|
||||
type, connectionId, requestResources.getIncremental());
|
||||
|
||||
watchedStatus = new WatchedStatus();
|
||||
watchedStatus.setType(type);
|
||||
connection.addWatchedResource(type, watchedStatus);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
watchedStatus = connection.getWatchedStatusByType(type);
|
||||
if (watchedStatus == null) {
|
||||
Loggers.MAIN.info("mcp: reconnect, type {}, connection-id {}, is incremental {}",
|
||||
type, connectionId, requestResources.getIncremental());
|
||||
watchedStatus = new WatchedStatus();
|
||||
watchedStatus.setType(type);
|
||||
connection.addWatchedResource(type, watchedStatus);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!watchedStatus.getLatestNonce().equals(requestResources.getResponseNonce())) {
|
||||
Loggers.MAIN.warn("mcp: request dis match, type {}, connection-id {}", type, connectionId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// This request is ack, we should record nonce.
|
||||
watchedStatus.setAckedNonce(requestResources.getResponseNonce());
|
||||
Loggers.MAIN.info("mcp: ack, type {}, connection-id {}, nonce {}", type, connectionId,
|
||||
requestResources.getResponseNonce());
|
||||
return false;
|
||||
}
|
||||
|
||||
public void handleEvent(ResourceSnapshot resourceSnapshot, Event event) {
|
||||
switch (event.getType()) {
|
||||
case Service:
|
||||
if (connections.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Loggers.MAIN.info("xds: event {} trigger push.", event.getType());
|
||||
|
||||
Mcp.Resources serviceEntryMcpResponse = buildMcpResourcesResponse(SERVICE_ENTRY_COLLECTION, resourceSnapshot);
|
||||
|
||||
for (AbstractConnection<Mcp.Resources> connection : connections.values()) {
|
||||
WatchedStatus watchedStatus = connection.getWatchedStatusByType(SERVICE_ENTRY_COLLECTION);
|
||||
if (watchedStatus != null) {
|
||||
connection.push(serviceEntryMcpResponse, watchedStatus);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Loggers.MAIN.warn("Invalid event {}, ignore it.", event.getType());
|
||||
}
|
||||
}
|
||||
|
||||
private Mcp.Resources buildMcpResourcesResponse(String type, ResourceSnapshot resourceSnapshot) {
|
||||
@SuppressWarnings("unchecked")
|
||||
ApiGenerator<Resource> serviceEntryGenerator = (ApiGenerator<Resource>) apiGeneratorFactory.getApiGenerator(type);
|
||||
List<Resource> rawResources = serviceEntryGenerator.generate(resourceSnapshot);
|
||||
|
||||
String nonce = NonceGenerator.generateNonce();
|
||||
return Mcp.Resources.newBuilder()
|
||||
.setCollection(type)
|
||||
.addAllResources(rawResources)
|
||||
.setSystemVersionInfo(resourceSnapshot.getVersion())
|
||||
.setNonce(nonce).build();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.mcp;
|
||||
|
||||
import com.alibaba.nacos.istio.api.ApiGenerator;
|
||||
import com.alibaba.nacos.istio.common.ResourceSnapshot;
|
||||
import com.alibaba.nacos.istio.model.ServiceEntryWrapper;
|
||||
import com.google.protobuf.Any;
|
||||
import istio.mcp.v1alpha1.MetadataOuterClass;
|
||||
import istio.mcp.v1alpha1.ResourceOuterClass.Resource;
|
||||
import istio.networking.v1alpha3.ServiceEntryOuterClass;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.alibaba.nacos.istio.api.ApiConstants.SERVICE_ENTRY_PROTO;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
public class ServiceEntryMcpGenerator implements ApiGenerator<Resource> {
|
||||
|
||||
private volatile static ServiceEntryMcpGenerator singleton = null;
|
||||
|
||||
public static ServiceEntryMcpGenerator getInstance() {
|
||||
if (singleton == null) {
|
||||
synchronized (ServiceEntryMcpGenerator.class) {
|
||||
if (singleton == null) {
|
||||
singleton = new ServiceEntryMcpGenerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
return singleton;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Resource> generate(ResourceSnapshot resourceSnapshot) {
|
||||
List<Resource> result = new ArrayList<>();
|
||||
|
||||
List<ServiceEntryWrapper> serviceEntries = resourceSnapshot.getServiceEntries();
|
||||
for (ServiceEntryWrapper serviceEntryWrapper : serviceEntries) {
|
||||
MetadataOuterClass.Metadata metadata = serviceEntryWrapper.getMetadata();
|
||||
ServiceEntryOuterClass.ServiceEntry serviceEntry = serviceEntryWrapper.getServiceEntry();
|
||||
|
||||
Any any = Any.newBuilder().setValue(serviceEntry.toByteString()).setTypeUrl(SERVICE_ENTRY_PROTO).build();
|
||||
|
||||
result.add(Resource.newBuilder().setBody(any).setMetadata(metadata).build());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.misc;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Stores some configurations for Istio integration.
|
||||
*
|
||||
* @author nkorange
|
||||
* @since 1.1.4
|
||||
*/
|
||||
@Component
|
||||
public class IstioConfig {
|
||||
|
||||
@Value("${nacos.istio.mcp.server.enabled:false}")
|
||||
private boolean serverEnabled = false;
|
||||
@Value("${nacos.istio.mcp.server.port:18848}")
|
||||
private int serverPort = 18848;
|
||||
@Value("${nacos.istio.mcp.push.interval:3000}")
|
||||
private int mcpPushInterval;
|
||||
@Value("${nacos.istio.domain.suffix:nacos}")
|
||||
private String domainSuffix;
|
||||
|
||||
public boolean isServerEnabled() {
|
||||
return serverEnabled;
|
||||
}
|
||||
|
||||
public int getServerPort() {
|
||||
return serverPort;
|
||||
}
|
||||
|
||||
public String getDomainSuffix() {
|
||||
return domainSuffix;
|
||||
}
|
||||
|
||||
public int getMcpPushInterval() {
|
||||
return mcpPushInterval;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.misc;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Loggers Holder.
|
||||
*
|
||||
* @author nkorange
|
||||
* @since 1.1.4
|
||||
*/
|
||||
public class Loggers {
|
||||
|
||||
public static final Logger MAIN = LoggerFactory.getLogger("com.alibaba.nacos.istio.main");
|
||||
}
|
||||
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.model;
|
||||
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
|
||||
import com.alibaba.nacos.naming.core.v2.pojo.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
public class IstioService {
|
||||
|
||||
private String name;
|
||||
|
||||
private String groupName;
|
||||
|
||||
private String namespace;
|
||||
|
||||
private Long revision;
|
||||
|
||||
private List<Instance> hosts;
|
||||
|
||||
private Date createTimeStamp;
|
||||
|
||||
public IstioService(Service service, ServiceInfo serviceInfo) {
|
||||
this.name = serviceInfo.getName();
|
||||
this.groupName = serviceInfo.getGroupName();
|
||||
this.namespace = service.getNamespace();
|
||||
this.revision = service.getRevision();
|
||||
// Record the create time of service to avoid trigger istio pull push.
|
||||
// See https://github.com/istio/istio/pull/30684
|
||||
createTimeStamp = new Date();
|
||||
|
||||
this.hosts = sanitizeServiceInfo(serviceInfo);
|
||||
}
|
||||
|
||||
public IstioService(Service service, ServiceInfo serviceInfo, IstioService old) {
|
||||
this.name = serviceInfo.getName();
|
||||
this.groupName = serviceInfo.getGroupName();
|
||||
this.namespace = service.getNamespace();
|
||||
this.revision = service.getRevision();
|
||||
// set the create time of service as old time to avoid trigger istio pull push.
|
||||
// See https://github.com/istio/istio/pull/30684
|
||||
createTimeStamp = old.getCreateTimeStamp();
|
||||
|
||||
this.hosts = sanitizeServiceInfo(serviceInfo);
|
||||
}
|
||||
|
||||
private List<Instance> sanitizeServiceInfo(ServiceInfo serviceInfo) {
|
||||
List<Instance> hosts = new ArrayList<>();
|
||||
|
||||
for (Instance instance : serviceInfo.getHosts()) {
|
||||
if (instance.isHealthy() && instance.isEnabled()) {
|
||||
hosts.add(instance);
|
||||
}
|
||||
}
|
||||
|
||||
// Panic mode, all instances are invalid, to push all instances to istio.
|
||||
if (hosts.isEmpty()) {
|
||||
hosts = serviceInfo.getHosts();
|
||||
}
|
||||
|
||||
return hosts;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public Long getRevision() {
|
||||
return revision;
|
||||
}
|
||||
|
||||
public List<Instance> getHosts() {
|
||||
return hosts;
|
||||
}
|
||||
|
||||
public Date getCreateTimeStamp() {
|
||||
return createTimeStamp;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.model;
|
||||
|
||||
import istio.mcp.v1alpha1.MetadataOuterClass.Metadata;
|
||||
import istio.networking.v1alpha3.ServiceEntryOuterClass.ServiceEntry;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
public class ServiceEntryWrapper {
|
||||
|
||||
private Metadata metadata;
|
||||
|
||||
private ServiceEntry serviceEntry;
|
||||
|
||||
public ServiceEntryWrapper(Metadata metadata, ServiceEntry serviceEntry) {
|
||||
this.metadata = metadata;
|
||||
this.serviceEntry = serviceEntry;
|
||||
}
|
||||
|
||||
public Metadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public ServiceEntry getServiceEntry() {
|
||||
return serviceEntry;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.server;
|
||||
|
||||
import com.alibaba.nacos.istio.common.NacosResourceManager;
|
||||
import com.alibaba.nacos.istio.mcp.NacosMcpService;
|
||||
import com.alibaba.nacos.istio.misc.IstioConfig;
|
||||
import com.alibaba.nacos.istio.misc.Loggers;
|
||||
import com.alibaba.nacos.istio.xds.NacosXdsService;
|
||||
import io.grpc.Server;
|
||||
import io.grpc.ServerBuilder;
|
||||
import io.grpc.ServerInterceptors;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
@Service
|
||||
public class IstioServer {
|
||||
|
||||
private Server server;
|
||||
|
||||
@Autowired
|
||||
private IstioConfig istioConfig;
|
||||
|
||||
@Autowired
|
||||
private ServerInterceptor serverInterceptor;
|
||||
|
||||
@Autowired
|
||||
private NacosMcpService nacosMcpService;
|
||||
|
||||
@Autowired
|
||||
private NacosXdsService nacosXdsService;
|
||||
|
||||
@Autowired
|
||||
private NacosResourceManager nacosResourceManager;
|
||||
|
||||
/**
|
||||
* Start.
|
||||
*
|
||||
* @throws IOException io exception
|
||||
*/
|
||||
@PostConstruct
|
||||
public void start() throws IOException {
|
||||
|
||||
if (!istioConfig.isServerEnabled()) {
|
||||
Loggers.MAIN.info("The Nacos Istio server is disabled.");
|
||||
return;
|
||||
}
|
||||
nacosResourceManager.start();
|
||||
|
||||
Loggers.MAIN.info("Nacos Istio server, starting Nacos Istio server...");
|
||||
|
||||
server = ServerBuilder.forPort(istioConfig.getServerPort()).addService(ServerInterceptors.intercept(nacosMcpService, serverInterceptor))
|
||||
.addService(ServerInterceptors.intercept(nacosXdsService, serverInterceptor)).build();
|
||||
server.start();
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
System.out.println("Stopping Nacos Istio server...");
|
||||
IstioServer.this.stop();
|
||||
System.out.println("Nacos Istio server stopped...");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop.
|
||||
*/
|
||||
public void stop() {
|
||||
if (server != null) {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.server;
|
||||
|
||||
import com.alibaba.nacos.istio.misc.Loggers;
|
||||
import io.grpc.Grpc;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.ServerCall;
|
||||
import io.grpc.ServerCallHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
@Component
|
||||
public class ServerInterceptor implements io.grpc.ServerInterceptor {
|
||||
|
||||
@Override
|
||||
public <R, T> ServerCall.Listener<R> interceptCall(ServerCall<R, T> call, Metadata headers,
|
||||
ServerCallHandler<R, T> next) {
|
||||
SocketAddress address = call.getAttributes().get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR);
|
||||
String methodName = call.getMethodDescriptor().getFullMethodName();
|
||||
|
||||
Loggers.MAIN.info("remote address: {}, method: {}", address, methodName);
|
||||
|
||||
return next.startCall(call, headers);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.util;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.istio.model.IstioService;
|
||||
import com.alibaba.nacos.istio.model.ServiceEntryWrapper;
|
||||
import com.alibaba.nacos.naming.core.v2.pojo.Service;
|
||||
import com.google.protobuf.Timestamp;
|
||||
import istio.mcp.v1alpha1.MetadataOuterClass.Metadata;
|
||||
import istio.networking.v1alpha3.GatewayOuterClass;
|
||||
import istio.networking.v1alpha3.ServiceEntryOuterClass.ServiceEntry;
|
||||
import istio.networking.v1alpha3.WorkloadEntryOuterClass.WorkloadEntry;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
public class IstioCrdUtil {
|
||||
|
||||
public static final String VALID_DEFAULT_GROUP_NAME = "DEFAULT-GROUP";
|
||||
|
||||
private static final String ISTIO_HOSTNAME = "istio.hostname";
|
||||
|
||||
public static final String VALID_LABEL_KEY_FORMAT = "^([a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?)*/)?((?:[A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$";
|
||||
public static final String VALID_LABEL_VALUE_FORMAT = "^((?:[A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$";
|
||||
|
||||
public static String buildServiceNameForServiceEntry(Service service) {
|
||||
String group = !Constants.DEFAULT_GROUP.equals(service.getGroup()) ? service.getGroup() : VALID_DEFAULT_GROUP_NAME;
|
||||
|
||||
// DEFAULT_GROUP is invalid for istio,because the istio host only supports: [0-9],[A-Z],[a-z],-,*
|
||||
return service.getName() + "." + group + "." + service.getNamespace();
|
||||
}
|
||||
|
||||
public static ServiceEntryWrapper buildServiceEntry(String serviceName, String domainSuffix,IstioService istioService) {
|
||||
if (istioService.getHosts().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ServiceEntry.Builder serviceEntryBuilder = ServiceEntry
|
||||
.newBuilder().setResolution(ServiceEntry.Resolution.STATIC)
|
||||
.setLocation(ServiceEntry.Location.MESH_INTERNAL);
|
||||
|
||||
int port = 0;
|
||||
String protocol = "http";
|
||||
String hostname = serviceName;
|
||||
|
||||
for (Instance instance : istioService.getHosts()) {
|
||||
if (port == 0) {
|
||||
port = instance.getPort();
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(instance.getMetadata().get("protocol"))) {
|
||||
protocol = instance.getMetadata().get("protocol");
|
||||
|
||||
if ("triple".equals(protocol) || "tri".equals(protocol)){
|
||||
protocol = "grpc";
|
||||
}
|
||||
}
|
||||
|
||||
String metaHostname = instance.getMetadata().get(ISTIO_HOSTNAME);
|
||||
if (StringUtils.isNotEmpty(metaHostname)) {
|
||||
hostname = metaHostname;
|
||||
}
|
||||
|
||||
if (!instance.isHealthy() || !instance.isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<String, String> metadata = new HashMap<>(1 << 3);
|
||||
if (StringUtils.isNotEmpty(instance.getClusterName())) {
|
||||
metadata.put("cluster", instance.getClusterName());
|
||||
}
|
||||
|
||||
for (Map.Entry<String,String> entry : instance.getMetadata().entrySet()){
|
||||
if (!Pattern.matches(VALID_LABEL_KEY_FORMAT, entry.getKey())){
|
||||
continue;
|
||||
}
|
||||
if (!Pattern.matches(VALID_LABEL_VALUE_FORMAT, entry.getValue())){
|
||||
continue;
|
||||
}
|
||||
metadata.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
WorkloadEntry workloadEntry = WorkloadEntry.newBuilder()
|
||||
.setAddress(instance.getIp()).setWeight((int) instance.getWeight())
|
||||
.putAllLabels(metadata).putPorts(protocol, instance.getPort()).build();
|
||||
serviceEntryBuilder.addEndpoints(workloadEntry);
|
||||
}
|
||||
|
||||
serviceEntryBuilder.addHosts(hostname + "." + domainSuffix).addPorts(
|
||||
GatewayOuterClass.Port.newBuilder().setNumber(port).setName(protocol).setProtocol(protocol.toUpperCase()).build());
|
||||
ServiceEntry serviceEntry = serviceEntryBuilder.build();
|
||||
|
||||
Date createTimestamp = istioService.getCreateTimeStamp();
|
||||
Metadata metadata = Metadata.newBuilder()
|
||||
.setName(istioService.getNamespace() + "/" + serviceName)
|
||||
.putAnnotations("virtual", "1")
|
||||
.putLabels("registryType", "nacos")
|
||||
.setCreateTime(Timestamp.newBuilder().setSeconds(createTimestamp.getTime() / 1000).build())
|
||||
.setVersion(String.valueOf(istioService.getRevision())).build();
|
||||
|
||||
return new ServiceEntryWrapper(metadata, serviceEntry);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.util;
|
||||
|
||||
import com.alibaba.nacos.common.executor.ExecutorFactory;
|
||||
import com.alibaba.nacos.common.executor.NameThreadFactory;
|
||||
import com.alibaba.nacos.core.utils.ClassUtils;
|
||||
import com.alibaba.nacos.istio.IstioApp;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
public class IstioExecutor {
|
||||
|
||||
private static final ScheduledExecutorService NACOS_RESOURCE_WATCHER = ExecutorFactory.Managed
|
||||
.newScheduledExecutorService(ClassUtils.getCanonicalName(IstioApp.class),
|
||||
EnvUtil.getAvailableProcessors(2),
|
||||
new NameThreadFactory("com.alibaba.nacos.istio.resource.watcher"));
|
||||
|
||||
private static final ExecutorService EVENT_HANDLE_EXECUTOR = ExecutorFactory.Managed
|
||||
.newSingleExecutorService(ClassUtils.getCanonicalName(IstioApp.class),
|
||||
new NameThreadFactory("com.alibaba.nacos.istio.event.handle"));
|
||||
|
||||
|
||||
public static void registerNacosResourceWatcher(Runnable watcher, long initialDelay, long period) {
|
||||
NACOS_RESOURCE_WATCHER.scheduleAtFixedRate(watcher, initialDelay, period, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public static <V> Future<V> asyncHandleEvent(Callable<V> task) {
|
||||
return EVENT_HANDLE_EXECUTOR.submit(task);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.util;
|
||||
|
||||
import com.alibaba.nacos.common.utils.UuidUtils;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
public class NonceGenerator {
|
||||
|
||||
public static String generateNonce() {
|
||||
return UuidUtils.generateUuid().replace("-", "");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.xds;
|
||||
|
||||
import com.alibaba.nacos.istio.api.ApiGenerator;
|
||||
import com.alibaba.nacos.istio.common.ResourceSnapshot;
|
||||
import com.google.protobuf.Any;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
public class EmptyXdsGenerator implements ApiGenerator<Any> {
|
||||
|
||||
private volatile static EmptyXdsGenerator singleton = null;
|
||||
|
||||
public static EmptyXdsGenerator getInstance() {
|
||||
if (singleton == null) {
|
||||
synchronized (EmptyXdsGenerator.class) {
|
||||
if (singleton == null) {
|
||||
singleton = new EmptyXdsGenerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
return singleton;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Any> generate(ResourceSnapshot resourceSnapshot) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.xds;
|
||||
|
||||
import com.alibaba.nacos.istio.api.ApiGenerator;
|
||||
import com.alibaba.nacos.istio.api.ApiGeneratorFactory;
|
||||
import com.alibaba.nacos.istio.common.*;
|
||||
import com.alibaba.nacos.istio.misc.Loggers;
|
||||
import com.alibaba.nacos.istio.util.NonceGenerator;
|
||||
import com.google.protobuf.Any;
|
||||
import io.envoyproxy.envoy.service.discovery.v3.AggregatedDiscoveryServiceGrpc;
|
||||
import io.envoyproxy.envoy.service.discovery.v3.DiscoveryRequest;
|
||||
import io.envoyproxy.envoy.service.discovery.v3.DiscoveryResponse;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static com.alibaba.nacos.istio.api.ApiConstants.MESH_CONFIG_PROTO_PACKAGE;
|
||||
import static com.alibaba.nacos.istio.api.ApiConstants.SERVICE_ENTRY_PROTO_PACKAGE;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
@Service
|
||||
public class NacosXdsService extends AggregatedDiscoveryServiceGrpc.AggregatedDiscoveryServiceImplBase {
|
||||
|
||||
private final Map<String, AbstractConnection<DiscoveryResponse>> connections = new ConcurrentHashMap<>(16);
|
||||
|
||||
public boolean hasClientConnection() {
|
||||
return connections.size() != 0;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
ApiGeneratorFactory apiGeneratorFactory;
|
||||
|
||||
@Autowired
|
||||
NacosResourceManager resourceManager;
|
||||
|
||||
@Override
|
||||
public StreamObserver<DiscoveryRequest> streamAggregatedResources(StreamObserver<DiscoveryResponse> responseObserver) {
|
||||
// TODO add authN
|
||||
|
||||
// Init snapshot of nacos service info.
|
||||
resourceManager.initResourceSnapshot();
|
||||
AbstractConnection<DiscoveryResponse> newConnection = new XdsConnection(responseObserver);
|
||||
|
||||
return new StreamObserver<DiscoveryRequest>() {
|
||||
private boolean initRequest = true;
|
||||
|
||||
@Override
|
||||
public void onNext(DiscoveryRequest discoveryRequest) {
|
||||
// init connection
|
||||
if (initRequest) {
|
||||
newConnection.setConnectionId(discoveryRequest.getNode().getId());
|
||||
connections.put(newConnection.getConnectionId(), newConnection);
|
||||
initRequest = false;
|
||||
}
|
||||
|
||||
process(discoveryRequest, newConnection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable throwable) {
|
||||
Loggers.MAIN.error("xds: {} stream error.", newConnection.getConnectionId(), throwable);
|
||||
clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
Loggers.MAIN.info("xds: {} stream close.", newConnection.getConnectionId());
|
||||
responseObserver.onCompleted();
|
||||
clear();
|
||||
}
|
||||
|
||||
private void clear() {
|
||||
connections.remove(newConnection.getConnectionId());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void process(DiscoveryRequest discoveryRequest, AbstractConnection<DiscoveryResponse> connection) {
|
||||
if (!shouldPush(discoveryRequest, connection)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DiscoveryResponse response = buildDiscoveryResponse(discoveryRequest.getTypeUrl(), resourceManager.getResourceSnapshot());
|
||||
connection.push(response, connection.getWatchedStatusByType(discoveryRequest.getTypeUrl()));
|
||||
}
|
||||
|
||||
private boolean shouldPush(DiscoveryRequest discoveryRequest, AbstractConnection<DiscoveryResponse> connection) {
|
||||
String type = discoveryRequest.getTypeUrl();
|
||||
String connectionId = connection.getConnectionId();
|
||||
|
||||
// Suitable for bug of istio
|
||||
// See https://github.com/istio/istio/pull/34633
|
||||
if (type.equals(MESH_CONFIG_PROTO_PACKAGE)) {
|
||||
Loggers.MAIN.info("xds: type {} should be ignored.", type);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (discoveryRequest.getErrorDetail().getCode() != 0) {
|
||||
Loggers.MAIN.error("xds: ACK error, connection-id: {}, code: {}, message: {}",
|
||||
connectionId,
|
||||
discoveryRequest.getErrorDetail().getCode(),
|
||||
discoveryRequest.getErrorDetail().getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
WatchedStatus watchedStatus;
|
||||
if (discoveryRequest.getResponseNonce().isEmpty()) {
|
||||
Loggers.MAIN.info("xds: init request, type {}, connection-id {}, version {}",
|
||||
type, connectionId, discoveryRequest.getVersionInfo());
|
||||
watchedStatus = new WatchedStatus();
|
||||
watchedStatus.setType(discoveryRequest.getTypeUrl());
|
||||
connection.addWatchedResource(discoveryRequest.getTypeUrl(), watchedStatus);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
watchedStatus = connection.getWatchedStatusByType(discoveryRequest.getTypeUrl());
|
||||
if (watchedStatus == null) {
|
||||
Loggers.MAIN.info("xds: reconnect, type {}, connection-id {}, version {}, nonce {}.",
|
||||
type, connectionId, discoveryRequest.getVersionInfo(), discoveryRequest.getResponseNonce());
|
||||
watchedStatus = new WatchedStatus();
|
||||
watchedStatus.setType(discoveryRequest.getTypeUrl());
|
||||
connection.addWatchedResource(discoveryRequest.getTypeUrl(), watchedStatus);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!watchedStatus.getLatestNonce().equals(discoveryRequest.getResponseNonce())) {
|
||||
Loggers.MAIN.warn("xds: request dis match, type {}, connection-id {}",
|
||||
discoveryRequest.getTypeUrl(),
|
||||
connection.getConnectionId());
|
||||
return false;
|
||||
}
|
||||
|
||||
// This request is ack, we should record version and nonce.
|
||||
watchedStatus.setAckedVersion(discoveryRequest.getVersionInfo());
|
||||
watchedStatus.setAckedNonce(discoveryRequest.getResponseNonce());
|
||||
Loggers.MAIN.info("xds: ack, type {}, connection-id {}, version {}, nonce {}", type, connectionId,
|
||||
discoveryRequest.getVersionInfo(), discoveryRequest.getResponseNonce());
|
||||
return false;
|
||||
}
|
||||
|
||||
public void handleEvent(ResourceSnapshot resourceSnapshot, Event event) {
|
||||
switch (event.getType()) {
|
||||
case Service:
|
||||
if (connections.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Loggers.MAIN.info("xds: event {} trigger push.", event.getType());
|
||||
|
||||
// Service Entry via MCP
|
||||
DiscoveryResponse serviceEntryResponse = buildDiscoveryResponse(SERVICE_ENTRY_PROTO_PACKAGE, resourceSnapshot);
|
||||
// TODO CDS, EDS
|
||||
|
||||
for (AbstractConnection<DiscoveryResponse> connection : connections.values()) {
|
||||
// Service Entry via MCP
|
||||
WatchedStatus watchedStatus = connection.getWatchedStatusByType(SERVICE_ENTRY_PROTO_PACKAGE);
|
||||
if (watchedStatus != null) {
|
||||
connection.push(serviceEntryResponse, watchedStatus);
|
||||
}
|
||||
// TODO CDS, EDS
|
||||
}
|
||||
break;
|
||||
case Endpoint:
|
||||
Loggers.MAIN.warn("Currently, endpoint event is not supported.");
|
||||
break;
|
||||
default:
|
||||
Loggers.MAIN.warn("Invalid event {}, ignore it.", event.getType());
|
||||
}
|
||||
}
|
||||
|
||||
private DiscoveryResponse buildDiscoveryResponse(String type, ResourceSnapshot resourceSnapshot) {
|
||||
@SuppressWarnings("unchecked")
|
||||
ApiGenerator<Any> serviceEntryGenerator = (ApiGenerator<Any>) apiGeneratorFactory.getApiGenerator(type);
|
||||
List<Any> rawResources = serviceEntryGenerator.generate(resourceSnapshot);
|
||||
|
||||
String nonce = NonceGenerator.generateNonce();
|
||||
return DiscoveryResponse.newBuilder()
|
||||
.setTypeUrl(type)
|
||||
.addAllResources(rawResources)
|
||||
.setVersionInfo(resourceSnapshot.getVersion())
|
||||
.setNonce(nonce).build();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.xds;
|
||||
|
||||
import com.alibaba.nacos.istio.api.ApiGenerator;
|
||||
import com.alibaba.nacos.istio.common.ResourceSnapshot;
|
||||
import com.alibaba.nacos.istio.model.ServiceEntryWrapper;
|
||||
import com.google.protobuf.Any;
|
||||
import istio.mcp.v1alpha1.MetadataOuterClass.Metadata;
|
||||
import istio.mcp.v1alpha1.ResourceOuterClass.Resource;
|
||||
import istio.networking.v1alpha3.ServiceEntryOuterClass.ServiceEntry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.alibaba.nacos.istio.api.ApiConstants.*;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
public final class ServiceEntryXdsGenerator implements ApiGenerator<Any> {
|
||||
|
||||
private volatile static ServiceEntryXdsGenerator singleton = null;
|
||||
|
||||
public static ServiceEntryXdsGenerator getInstance() {
|
||||
if (singleton == null) {
|
||||
synchronized (ServiceEntryXdsGenerator.class) {
|
||||
if (singleton == null) {
|
||||
singleton = new ServiceEntryXdsGenerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
return singleton;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Any> generate(ResourceSnapshot resourceSnapshot) {
|
||||
List<Resource> resources = new ArrayList<>();
|
||||
|
||||
List<ServiceEntryWrapper> serviceEntries = resourceSnapshot.getServiceEntries();
|
||||
for (ServiceEntryWrapper serviceEntryWrapper : serviceEntries) {
|
||||
Metadata metadata = serviceEntryWrapper.getMetadata();
|
||||
ServiceEntry serviceEntry = serviceEntryWrapper.getServiceEntry();
|
||||
|
||||
Any any = Any.newBuilder().setValue(serviceEntry.toByteString()).setTypeUrl(SERVICE_ENTRY_PROTO).build();
|
||||
|
||||
resources.add(Resource.newBuilder().setBody(any).setMetadata(metadata).build());
|
||||
}
|
||||
|
||||
List<Any> result = new ArrayList<>();
|
||||
for (Resource resource : resources) {
|
||||
result.add(Any.newBuilder().setValue(resource.toByteString()).setTypeUrl(MCP_RESOURCE_PROTO).build());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.istio.xds;
|
||||
|
||||
import com.alibaba.nacos.istio.common.AbstractConnection;
|
||||
import com.alibaba.nacos.istio.common.WatchedStatus;
|
||||
import com.alibaba.nacos.istio.misc.Loggers;
|
||||
import io.envoyproxy.envoy.service.discovery.v3.DiscoveryResponse;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
|
||||
/**
|
||||
* @author special.fy
|
||||
*/
|
||||
public class XdsConnection extends AbstractConnection<DiscoveryResponse> {
|
||||
|
||||
public XdsConnection(StreamObserver<DiscoveryResponse> streamObserver) {
|
||||
super(streamObserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void push(DiscoveryResponse response, WatchedStatus watchedStatus) {
|
||||
if (Loggers.MAIN.isDebugEnabled()) {
|
||||
Loggers.MAIN.debug("discoveryResponse: {}", response.toString());
|
||||
}
|
||||
|
||||
this.streamObserver.onNext(response);
|
||||
|
||||
// Update watched status
|
||||
watchedStatus.setLatestVersion(response.getVersionInfo());
|
||||
watchedStatus.setLatestNonce(response.getNonce());
|
||||
|
||||
Loggers.MAIN.info("xds: push, type: {}, connection-id {}, version {}, nonce {}, resource size {}.",
|
||||
watchedStatus.getType(),
|
||||
getConnectionId(),
|
||||
response.getVersionInfo(),
|
||||
response.getNonce(),
|
||||
response.getResourcesCount());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
#
|
||||
# Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
com.alibaba.nacos.istio.config.IstioEnabledFilter
|
||||
144
istio/src/main/resources/proto/gogoproto/gogo.proto
Normal file
144
istio/src/main/resources/proto/gogoproto/gogo.proto
Normal file
@ -0,0 +1,144 @@
|
||||
// Protocol Buffers for Go with Gadgets
|
||||
//
|
||||
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
|
||||
// http://github.com/gogo/protobuf
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto2";
|
||||
package gogoproto;
|
||||
|
||||
import "google/protobuf/descriptor.proto";
|
||||
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "GoGoProtos";
|
||||
option go_package = "github.com/gogo/protobuf/gogoproto";
|
||||
|
||||
extend google.protobuf.EnumOptions {
|
||||
optional bool goproto_enum_prefix = 62001;
|
||||
optional bool goproto_enum_stringer = 62021;
|
||||
optional bool enum_stringer = 62022;
|
||||
optional string enum_customname = 62023;
|
||||
optional bool enumdecl = 62024;
|
||||
}
|
||||
|
||||
extend google.protobuf.EnumValueOptions {
|
||||
optional string enumvalue_customname = 66001;
|
||||
}
|
||||
|
||||
extend google.protobuf.FileOptions {
|
||||
optional bool goproto_getters_all = 63001;
|
||||
optional bool goproto_enum_prefix_all = 63002;
|
||||
optional bool goproto_stringer_all = 63003;
|
||||
optional bool verbose_equal_all = 63004;
|
||||
optional bool face_all = 63005;
|
||||
optional bool gostring_all = 63006;
|
||||
optional bool populate_all = 63007;
|
||||
optional bool stringer_all = 63008;
|
||||
optional bool onlyone_all = 63009;
|
||||
|
||||
optional bool equal_all = 63013;
|
||||
optional bool description_all = 63014;
|
||||
optional bool testgen_all = 63015;
|
||||
optional bool benchgen_all = 63016;
|
||||
optional bool marshaler_all = 63017;
|
||||
optional bool unmarshaler_all = 63018;
|
||||
optional bool stable_marshaler_all = 63019;
|
||||
|
||||
optional bool sizer_all = 63020;
|
||||
|
||||
optional bool goproto_enum_stringer_all = 63021;
|
||||
optional bool enum_stringer_all = 63022;
|
||||
|
||||
optional bool unsafe_marshaler_all = 63023;
|
||||
optional bool unsafe_unmarshaler_all = 63024;
|
||||
|
||||
optional bool goproto_extensions_map_all = 63025;
|
||||
optional bool goproto_unrecognized_all = 63026;
|
||||
optional bool gogoproto_import = 63027;
|
||||
optional bool protosizer_all = 63028;
|
||||
optional bool compare_all = 63029;
|
||||
optional bool typedecl_all = 63030;
|
||||
optional bool enumdecl_all = 63031;
|
||||
|
||||
optional bool goproto_registration = 63032;
|
||||
optional bool messagename_all = 63033;
|
||||
|
||||
optional bool goproto_sizecache_all = 63034;
|
||||
optional bool goproto_unkeyed_all = 63035;
|
||||
}
|
||||
|
||||
extend google.protobuf.MessageOptions {
|
||||
optional bool goproto_getters = 64001;
|
||||
optional bool goproto_stringer = 64003;
|
||||
optional bool verbose_equal = 64004;
|
||||
optional bool face = 64005;
|
||||
optional bool gostring = 64006;
|
||||
optional bool populate = 64007;
|
||||
optional bool stringer = 67008;
|
||||
optional bool onlyone = 64009;
|
||||
|
||||
optional bool equal = 64013;
|
||||
optional bool description = 64014;
|
||||
optional bool testgen = 64015;
|
||||
optional bool benchgen = 64016;
|
||||
optional bool marshaler = 64017;
|
||||
optional bool unmarshaler = 64018;
|
||||
optional bool stable_marshaler = 64019;
|
||||
|
||||
optional bool sizer = 64020;
|
||||
|
||||
optional bool unsafe_marshaler = 64023;
|
||||
optional bool unsafe_unmarshaler = 64024;
|
||||
|
||||
optional bool goproto_extensions_map = 64025;
|
||||
optional bool goproto_unrecognized = 64026;
|
||||
|
||||
optional bool protosizer = 64028;
|
||||
optional bool compare = 64029;
|
||||
|
||||
optional bool typedecl = 64030;
|
||||
|
||||
optional bool messagename = 64033;
|
||||
|
||||
optional bool goproto_sizecache = 64034;
|
||||
optional bool goproto_unkeyed = 64035;
|
||||
}
|
||||
|
||||
extend google.protobuf.FieldOptions {
|
||||
optional bool nullable = 65001;
|
||||
optional bool embed = 65002;
|
||||
optional string customtype = 65003;
|
||||
optional string customname = 65004;
|
||||
optional string jsontag = 65005;
|
||||
optional string moretags = 65006;
|
||||
optional string casttype = 65007;
|
||||
optional string castkey = 65008;
|
||||
optional string castvalue = 65009;
|
||||
|
||||
optional bool stdtime = 65010;
|
||||
optional bool stdduration = 65011;
|
||||
optional bool wktpointer = 65012;
|
||||
|
||||
}
|
||||
155
istio/src/main/resources/proto/google/protobuf/any.proto
Normal file
155
istio/src/main/resources/proto/google/protobuf/any.proto
Normal file
@ -0,0 +1,155 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
option go_package = "github.com/golang/protobuf/ptypes/any";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "AnyProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
|
||||
// `Any` contains an arbitrary serialized protocol buffer message along with a
|
||||
// URL that describes the type of the serialized message.
|
||||
//
|
||||
// Protobuf library provides support to pack/unpack Any values in the form
|
||||
// of utility functions or additional generated methods of the Any type.
|
||||
//
|
||||
// Example 1: Pack and unpack a message in C++.
|
||||
//
|
||||
// Foo foo = ...;
|
||||
// Any any;
|
||||
// any.PackFrom(foo);
|
||||
// ...
|
||||
// if (any.UnpackTo(&foo)) {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// Example 2: Pack and unpack a message in Java.
|
||||
//
|
||||
// Foo foo = ...;
|
||||
// Any any = Any.pack(foo);
|
||||
// ...
|
||||
// if (any.is(Foo.class)) {
|
||||
// foo = any.unpack(Foo.class);
|
||||
// }
|
||||
//
|
||||
// Example 3: Pack and unpack a message in Python.
|
||||
//
|
||||
// foo = Foo(...)
|
||||
// any = Any()
|
||||
// any.Pack(foo)
|
||||
// ...
|
||||
// if any.Is(Foo.DESCRIPTOR):
|
||||
// any.Unpack(foo)
|
||||
// ...
|
||||
//
|
||||
// Example 4: Pack and unpack a message in Go
|
||||
//
|
||||
// foo := &pb.Foo{...}
|
||||
// any, err := ptypes.MarshalAny(foo)
|
||||
// ...
|
||||
// foo := &pb.Foo{}
|
||||
// if err := ptypes.UnmarshalAny(any, foo); err != nil {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// The pack methods provided by protobuf library will by default use
|
||||
// 'type.googleapis.com/full.type.name' as the type URL and the unpack
|
||||
// methods only use the fully qualified type name after the last '/'
|
||||
// in the type URL, for example "foo.bar.com/x/y.z" will yield type
|
||||
// name "y.z".
|
||||
//
|
||||
//
|
||||
// JSON
|
||||
// ====
|
||||
// The JSON representation of an `Any` value uses the regular
|
||||
// representation of the deserialized, embedded message, with an
|
||||
// additional field `@type` which contains the type URL. Example:
|
||||
//
|
||||
// package google.profile;
|
||||
// message Person {
|
||||
// string first_name = 1;
|
||||
// string last_name = 2;
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// "@type": "type.googleapis.com/google.profile.Person",
|
||||
// "firstName": <string>,
|
||||
// "lastName": <string>
|
||||
// }
|
||||
//
|
||||
// If the embedded message type is well-known and has a custom JSON
|
||||
// representation, that representation will be embedded adding a field
|
||||
// `value` which holds the custom JSON in addition to the `@type`
|
||||
// field. Example (for message [google.protobuf.Duration][]):
|
||||
//
|
||||
// {
|
||||
// "@type": "type.googleapis.com/google.protobuf.Duration",
|
||||
// "value": "1.212s"
|
||||
// }
|
||||
//
|
||||
message Any {
|
||||
// A URL/resource name that uniquely identifies the type of the serialized
|
||||
// protocol buffer message. This string must contain at least
|
||||
// one "/" character. The last segment of the URL's path must represent
|
||||
// the fully qualified name of the type (as in
|
||||
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
||||
// (e.g., leading "." is not accepted).
|
||||
//
|
||||
// In practice, teams usually precompile into the binary all types that they
|
||||
// expect it to use in the context of Any. However, for URLs which use the
|
||||
// scheme `http`, `https`, or no scheme, one can optionally set up a type
|
||||
// server that maps type URLs to message definitions as follows:
|
||||
//
|
||||
// * If no scheme is provided, `https` is assumed.
|
||||
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
||||
// value in binary format, or produce an error.
|
||||
// * Applications are allowed to cache lookup results based on the
|
||||
// URL, or have them precompiled into a binary to avoid any
|
||||
// lookup. Therefore, binary compatibility needs to be preserved
|
||||
// on changes to types. (Use versioned type names to manage
|
||||
// breaking changes.)
|
||||
//
|
||||
// Note: this functionality is not currently available in the official
|
||||
// protobuf release, and it is not used for type URLs beginning with
|
||||
// type.googleapis.com.
|
||||
//
|
||||
// Schemes other than `http`, `https` (or the empty scheme) might be
|
||||
// used with implementation specific semantics.
|
||||
//
|
||||
string type_url = 1;
|
||||
|
||||
// Must be a valid serialized protocol buffer of the above specified type.
|
||||
bytes value = 2;
|
||||
}
|
||||
165
istio/src/main/resources/proto/mcp/Readme.md
Normal file
165
istio/src/main/resources/proto/mcp/Readme.md
Normal file
@ -0,0 +1,165 @@
|
||||
// Copyright 2018 Istio Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
# Mesh Configuration Protocol (MCP)
|
||||
|
||||
## Introduction
|
||||
|
||||
This folder contains the proto buffers for the Mesh Configuration
|
||||
Protocol (MCP). MCP is based on
|
||||
[XDS](https://github.com/envoyproxy/data-plane-api/blob/master/xds_protocol.rst#streaming-grpc-subscriptions)
|
||||
and maintains conceptual alignment with it, despite the specific
|
||||
service and proto definitions being different.
|
||||
|
||||
## Overview
|
||||
|
||||
MCP is a subscription-based configuration distribution API. The
|
||||
configuration consumer (i.e. sink) requests updates for collections of
|
||||
resources from a configuration producer (i.e. source). The source
|
||||
pushes resource updates to the sink when resources are added, updated,
|
||||
or deleted. The sink positively ACK's the resource update, if it was
|
||||
accepted, and NACK's if it was rejected, e.g. because a resource was
|
||||
invalid. The source may push additional update once the previous
|
||||
update was ACK/NACK'd. The source should only have one outstanding
|
||||
update (per-collection) in flight at a time.
|
||||
|
||||
MCP is a pair of bidirectional streaming gRPC API services
|
||||
(`ResourceSource` and `ResourceSink`).
|
||||
|
||||
* The `ResourceSource` service is used when the resource source is the
|
||||
server and the sink is a client. By default, Galley implements the
|
||||
`ResourceSource` service and Pilot/Mixer connect as clients.
|
||||
|
||||
* The `ResourceSink` service is used when the resource source is a
|
||||
client and the sink is the server. Galley can be configured to
|
||||
optionally "dial-out" to a remote configuration sink, e.g. Pilot is in
|
||||
another cluster where it cannot, as a client, initiate
|
||||
connection to Galley. In this scenario, Pilot would implement the
|
||||
`ResourceSink` service and Galley would connect as a client.
|
||||
|
||||
ResourceSource and ResourceSink are semantically equivalent with
|
||||
regards to the message exchange. The only meaningful difference is who
|
||||
initiates the connection and opens the grpc stream.
|
||||
|
||||
## Data model
|
||||
|
||||
MCP is the mechanism of transport whereby Pilot and Mixer can be
|
||||
configured by a manager component. MCP defines a common per-resource
|
||||
metadata format and resource specific contents is defined elsewhere
|
||||
(e.g. <https://github.com/istio/api/tree/master/networking/v1alpha3>).
|
||||
|
||||
### Collections
|
||||
|
||||
Resources of the same type are organized into named
|
||||
collections. Istio API collection names are of the form
|
||||
`istio/<area>/<version>/<api>` where `<area>`, `<version>`, and `<api>`
|
||||
are defined by the [API style guidelines](../GUIDELINES.md). For
|
||||
example, the collection name for VirtualService is
|
||||
`istio/networking/v1alpha3/virtualservices`.
|
||||
|
||||
### Metadata
|
||||
|
||||
## Connection establishment
|
||||
|
||||
* `ResourceSource` service - The client is the resource sink. The
|
||||
client dials the server and establishes a new gRPC stream. The client
|
||||
sends RequestResources and receive Resources messages.
|
||||
|
||||

|
||||
|
||||
* `ResourceSink` service - The client is the resource source. The
|
||||
client dials the server and establishes a new gRPC stream. The server
|
||||
sends RequestResources and receive Resources messages.
|
||||
|
||||

|
||||
|
||||
## Configuration updates
|
||||
|
||||
The following overview applies to both ResourceSink and ResourceSource
|
||||
services, regardless of client/server roles.
|
||||
|
||||
The resource update protocol is derived from Incremental xDS. The
|
||||
protocol exchange is mostly the same except that resource hints have
|
||||
been removed. Most of the text and diagrams below are copied from the
|
||||
Incremental xDS docs and adjusted accordingly.
|
||||
|
||||
In MCP, resources are first organized by collection. Within each
|
||||
collection, resources are uniquely identifiable by their metadata
|
||||
name. Individual resources are versioned to differentiate newer
|
||||
versions of the same named resource.
|
||||
|
||||
A `RequestResource` message can be sent in two situations:
|
||||
|
||||
* Initial message in an MCP bidirectional change stream
|
||||
|
||||
* As an ACK or NACK response to a previous `Resources` message. In
|
||||
this case the `response_nonce` is set to the nonce value from the
|
||||
`Resources` message. ACK/NACK is determined by the presence of
|
||||
`error_detail` in the subsequent request.
|
||||
|
||||
The initial `RequestResources` messages includes the collection
|
||||
corresponding to the subscribed set of resources
|
||||
(e.g. VirtualService), the node sink identifier, and nonce fields, and
|
||||
initial_resource_version (more on that later). The source send a
|
||||
`Resources` message when the requested resources are available. After
|
||||
processing the `Resources` message , the sink sends a new
|
||||
`RequestResources` message on the stream, specifying the last version
|
||||
successfully applied and the nonce provided by the source.
|
||||
|
||||
The nonce field is used to pair `RequestResources` and `Resources`
|
||||
messages per collection. The source should only send one outstanding
|
||||
`Resource` message at a time (per-collection) and wait for the sink to
|
||||
ACK/NACK. Upon receiving an update, the sink is expected to send an
|
||||
ACK/NACK relatively quickly after decoding, validating, and persisting
|
||||
the update to its internal configuration store.
|
||||
|
||||
The source should ignore requests with stale and unknown nonces that
|
||||
do not match the nonce in the most recently sent `Resource` message.
|
||||
|
||||
### Success examples
|
||||
|
||||
The following example shows the sink receiving a sequence of changes
|
||||
which are successfully ACK'd.
|
||||
|
||||

|
||||
|
||||
The following example shows the same desired resource delivered with
|
||||
incremental updates. This example assumes incremental is supported by
|
||||
the source. When source does not support incremental updates, the
|
||||
pushed `Resources` will always have incremental set to false,
|
||||
regardles of whether the sink requested an incremental update. At any
|
||||
time, the source can decide to push a full-state update, ignoring the
|
||||
sink's request. Both sides must negotiate (i.e. agree) to use
|
||||
incremental on a per request/response basis for an update to be sent
|
||||
incrementally.
|
||||
|
||||

|
||||
|
||||
### Error example
|
||||
|
||||
The following example shows what happens when a change cannot be applied.
|
||||
|
||||

|
||||
|
||||
The sink should only NACK in _exceptional_ cases. For example, if a set of
|
||||
resources was invalid, malformed, or could not be decoded. NACK'd updates
|
||||
should raise an alarm for subsequent investigation by a human. The source
|
||||
should not resend the same set of resources that were previously NACK'd.
|
||||
Canary pushes to dedicated sinks may also be used to verify correctness
|
||||
(non-NACK) before pushing to a larger fleet of resource sinks.
|
||||
|
||||
The nonce in MCP is used to match RequestResources and Resources. On
|
||||
reconnect, the sinks may attempt to resume a session with the same
|
||||
source by specifying the known resources version with
|
||||
initial_resource_version for each collection.
|
||||
309
istio/src/main/resources/proto/mcp/v1alpha1/mcp.proto
Normal file
309
istio/src/main/resources/proto/mcp/v1alpha1/mcp.proto
Normal file
@ -0,0 +1,309 @@
|
||||
// Copyright 2018 Istio Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package istio.mcp.v1alpha1;
|
||||
|
||||
import "google/rpc/status.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
import "mcp/v1alpha1/resource.proto";
|
||||
|
||||
option go_package="istio.io/api/mcp/v1alpha1";
|
||||
option (gogoproto.equal_all) = true;
|
||||
|
||||
// Identifies a specific MCP sink node instance. The node identifier is
|
||||
// presented to the resource source, which may use this identifier
|
||||
// to distinguish per sink configuration for serving. This
|
||||
// information is not authoritative. Authoritative identity should come
|
||||
// from the underlying transport layer (e.g. rpc credentials).
|
||||
message SinkNode {
|
||||
// An opaque identifier for the MCP node.
|
||||
string id = 1;
|
||||
|
||||
// Opaque annotations extending the node identifier.
|
||||
map<string,string> annotations = 2;
|
||||
}
|
||||
|
||||
// A MeshConfigRequest requests a set of versioned resources of the
|
||||
// same type for a given client.
|
||||
message MeshConfigRequest {
|
||||
// The version_info provided in the request messages will be the
|
||||
// version_info received with the most recent successfully processed
|
||||
// response or empty on the first request. It is expected that no
|
||||
// new request is sent after a response is received until the client
|
||||
// instance is ready to ACK/NACK the new configuration. ACK/NACK
|
||||
// takes place by returning the new API config version as applied or
|
||||
// the previous API config version respectively. Each type_url (see
|
||||
// below) has an independent version associated with it.
|
||||
string version_info = 1;
|
||||
|
||||
// The sink node making the request.
|
||||
SinkNode sink_node = 2;
|
||||
|
||||
// Type of the resource that is being requested, e.g.
|
||||
// "type.googleapis.com/istio.io.networking.v1alpha3.VirtualService".
|
||||
string type_url = 3;
|
||||
|
||||
// The nonce corresponding to MeshConfigResponse being
|
||||
// ACK/NACKed. See above discussion on version_info and the
|
||||
// MeshConfigResponse nonce comment. This may be empty if no nonce is
|
||||
// available, e.g. at startup.
|
||||
string response_nonce = 4;
|
||||
|
||||
// This is populated when the previous MeshConfigResponse failed to
|
||||
// update configuration. The *message* field in *error_details*
|
||||
// provides the client internal exception related to the failure. It
|
||||
// is only intended for consumption during manual debugging, the
|
||||
// string provided is not guaranteed to be stable across client
|
||||
// versions.
|
||||
google.rpc.Status error_detail = 5;
|
||||
}
|
||||
|
||||
// A MeshConfigResponse delivers a set of versioned resources of the
|
||||
// same type in response to a MeshConfigRequest.
|
||||
message MeshConfigResponse {
|
||||
// The version of the response data.
|
||||
string version_info = 1;
|
||||
|
||||
// The response resources wrapped in the common MCP *Resource*
|
||||
// message.
|
||||
repeated Resource resources = 2 [(gogoproto.nullable) = false];
|
||||
|
||||
// Type URL for resources wrapped in the provided resources(s). This
|
||||
// must be consistent with the type_url in the wrapper messages if
|
||||
// resources is non-empty.
|
||||
string type_url = 3;
|
||||
|
||||
// The nonce provides a way to explicitly ack a specific
|
||||
// MeshConfigResponse in a following MeshConfigRequest. Additional
|
||||
// messages may have been sent by client to the management server for
|
||||
// the previous version on the stream prior to this
|
||||
// MeshConfigResponse, that were unprocessed at response send
|
||||
// time. The nonce allows the management server to ignore any
|
||||
// further MeshConfigRequests for the previous version until a
|
||||
// MeshConfigRequest bearing the nonce.
|
||||
string nonce = 4;
|
||||
}
|
||||
|
||||
// IncrementalMeshConfigRequest are be sent in 2 situations:
|
||||
//
|
||||
// 1. Initial message in a MCP bidirectional gRPC stream.
|
||||
//
|
||||
// 2. As a ACK or NACK response to a previous IncrementalMeshConfigResponse.
|
||||
// In this case the response_nonce is set to the nonce value in the Response.
|
||||
// ACK or NACK is determined by the absence or presence of error_detail.
|
||||
message IncrementalMeshConfigRequest {
|
||||
// The sink node making the request.
|
||||
SinkNode sink_node = 1;
|
||||
|
||||
// Type of the resource that is being requested, e.g.
|
||||
// "type.googleapis.com/istio.io.networking.v1alpha3.VirtualService".
|
||||
string type_url = 2;
|
||||
|
||||
|
||||
// When the IncrementalMeshConfigRequest is the first in a stream,
|
||||
// the initial_resource_versions must be populated. Otherwise,
|
||||
// initial_resource_versions must be omitted. The keys are the
|
||||
// resources names of the MCP resources known to the MCP client. The
|
||||
// values in the map are the associated resource level version info.
|
||||
map<string, string> initial_resource_versions = 3;
|
||||
|
||||
// When the IncrementalMeshConfigRequest is a ACK or NACK message in response
|
||||
// to a previous IncrementalMeshConfigResponse, the response_nonce must be the
|
||||
// nonce in the IncrementalMeshConfigResponse.
|
||||
// Otherwise response_nonce must be omitted.
|
||||
string response_nonce = 4;
|
||||
|
||||
// This is populated when the previous IncrementalMeshConfigResponses
|
||||
// failed to update configuration. The *message* field in *error_details*
|
||||
// provides the client internal exception related to the failure.
|
||||
google.rpc.Status error_detail = 5;
|
||||
}
|
||||
|
||||
// IncrementalMeshConfigResponses do not need to include a full
|
||||
// snapshot of the tracked resources. Instead they are a diff to the
|
||||
// state of a MCP client. Per resource versions allow servers and
|
||||
// clients to track state at the resource granularity. An MCP
|
||||
// incremental session is always in the context of a gRPC
|
||||
// bidirectional stream. This allows the MCP server to keep track of
|
||||
// the state of MCP clients connected to it.
|
||||
//
|
||||
// In Incremental MCP the nonce field is required and used to pair
|
||||
// IncrementalMeshConfigResponse to an IncrementalMeshConfigRequest
|
||||
// ACK or NACK. Optionally, a response message level
|
||||
// system_version_info is present for debugging purposes only.
|
||||
message IncrementalMeshConfigResponse {
|
||||
// The version of the response data (used for debugging).
|
||||
string system_version_info = 1;
|
||||
|
||||
// The response resources wrapped in the common MCP *Resource*
|
||||
// message. These are typed resources that match the type url in the
|
||||
// IncrementalMeshConfigRequest.
|
||||
repeated Resource resources = 2 [(gogoproto.nullable) = false];
|
||||
|
||||
// Resources names of resources that have be deleted and to be
|
||||
// removed from the MCP Client. Removed resources for missing
|
||||
// resources can be ignored.
|
||||
repeated string removed_resources = 3;
|
||||
|
||||
// The nonce provides a way for IncrementalMeshConfigRequests to
|
||||
// uniquely reference an IncrementalMeshConfigResponse. The nonce is
|
||||
// required.
|
||||
string nonce = 4;
|
||||
}
|
||||
|
||||
// The aggregated mesh configuration services allow a single
|
||||
// management server, via a single gRPC stream, to deliver all API
|
||||
// updates.
|
||||
service AggregatedMeshConfigService {
|
||||
// StreamAggregatedResources provides the ability to carefully
|
||||
// sequence updates across multiple resource types. A single stream
|
||||
// is used with multiple independent MeshConfigRequest /
|
||||
// MeshConfigResponses sequences multiplexed via the type URL.
|
||||
rpc StreamAggregatedResources(stream MeshConfigRequest)
|
||||
returns (stream MeshConfigResponse) {
|
||||
}
|
||||
|
||||
// IncrementalAggregatedResources provides the ability to incrementally
|
||||
// update the resources on the client. This supports the goal of
|
||||
// scalability of MCP resources.
|
||||
rpc IncrementalAggregatedResources(stream IncrementalMeshConfigRequest)
|
||||
returns (stream IncrementalMeshConfigResponse) {
|
||||
}
|
||||
}
|
||||
|
||||
// A RequestResource can be sent in two situations:
|
||||
//
|
||||
// Initial message in an MCP bidirectional change stream
|
||||
// as an ACK or NACK response to a previous Resources. In
|
||||
// this case the response_nonce is set to the nonce value
|
||||
// in the Resources. ACK/NACK is determined by the presence
|
||||
// of error_detail.
|
||||
//
|
||||
// * ACK (nonce!="",error_details==nil)
|
||||
// * NACK (nonce!="",error_details!=nil)
|
||||
// * New/Update request (nonce=="",error_details ignored)
|
||||
//
|
||||
message RequestResources {
|
||||
// The sink node making the request.
|
||||
SinkNode sink_node = 1;
|
||||
|
||||
// Type of resource collection that is being requested, e.g.
|
||||
//
|
||||
// istio/networking/v1alpha3/VirtualService
|
||||
// k8s/<apiVersion>/<kind>
|
||||
string collection = 2;
|
||||
|
||||
// When the RequestResources is the first in a stream, the initial_resource_versions must
|
||||
// be populated. Otherwise, initial_resource_versions must be omitted. The keys are the
|
||||
// resources names of the MCP resources known to the MCP client. The values in the map
|
||||
// are the associated resource level version info.
|
||||
map<string, string> initial_resource_versions = 3;
|
||||
|
||||
// When the RequestResources is an ACK or NACK message in response to a previous RequestResources,
|
||||
// the response_nonce must be the nonce in the RequestResources. Otherwise response_nonce must
|
||||
// be omitted.
|
||||
string response_nonce = 4;
|
||||
|
||||
// This is populated when the previously received resources could not be applied
|
||||
// The *message* field in *error_details* provides the source internal error
|
||||
// related to the failure.
|
||||
google.rpc.Status error_detail = 5;
|
||||
|
||||
// Request an incremental update for the specified collection. The source may choose to
|
||||
// honor this request or ignore and and provide a full-state update in the corresponding
|
||||
// `Resource` response.
|
||||
bool incremental = 6;
|
||||
}
|
||||
|
||||
// Resources do not need to include a full snapshot of the tracked
|
||||
// resources. Instead they are a diff to the state of a MCP client.
|
||||
// Per resource versions allow sources and sinks to track state at
|
||||
// the resource granularity. An MCP incremental session is always
|
||||
// in the context of a gRPC bidirectional stream. This allows the
|
||||
// MCP source to keep track of the state of MCP sink connected to
|
||||
// it.
|
||||
//
|
||||
// In Incremental MCP the nonce field is required and used to pair
|
||||
// Resources to an RequestResources ACK or NACK.
|
||||
message Resources {
|
||||
// The version of the response data (used for debugging).
|
||||
string system_version_info = 1;
|
||||
|
||||
// Type of resource collection that is being requested, e.g.
|
||||
//
|
||||
// istio/networking/v1alpha3/VirtualService
|
||||
// k8s/<apiVersion>/<kind>
|
||||
string collection = 2;
|
||||
|
||||
// The response resources wrapped in the common MCP *Resource* message.
|
||||
// These are typed resources that match the type url in the
|
||||
// RequestResources message.
|
||||
//
|
||||
// When `incremental` is true, this contains an array of resources to add/update
|
||||
// for the specified collection. This modifies the existing collection at the sink
|
||||
//
|
||||
// When `incremental` is false, this contains the full set of resources for the
|
||||
// specified collection. This replaces any previously delivered resources.
|
||||
repeated Resource resources = 3 [(gogoproto.nullable) = false];
|
||||
|
||||
// Names of resources that have been deleted and to be
|
||||
// removed from the MCP sink node. Removed resources for missing
|
||||
// resources can be ignored.
|
||||
//
|
||||
// When `incremental` is true, this contains an array of resource names to remove
|
||||
// for the specified collection. This modifies the existing resource collection at
|
||||
// the sink.
|
||||
//
|
||||
// When `incremental` is false, this field should be ignored.
|
||||
repeated string removed_resources = 4;
|
||||
|
||||
// Required. The nonce provides a way for RequestChange to uniquely
|
||||
// reference a RequestResources.
|
||||
string nonce = 5;
|
||||
|
||||
// This resource response is an incremental update. The source should only send
|
||||
// incremental updates if the sink requested them.
|
||||
bool incremental = 6;
|
||||
}
|
||||
|
||||
// ResourceSource and ResourceSink services are semantically
|
||||
// equivalent with regards to the message exchange. The only meaningful
|
||||
// difference is who initiates the connection and opens the stream. The
|
||||
// following high-level overview applies to both service variants.
|
||||
//
|
||||
// After the connection and streams have been established, the sink sends
|
||||
// a RequestResource messages to request the initial set of resources. The
|
||||
// source sends a Resource message when new resources are available for the
|
||||
// requested type. In response, the sink sends another RequestResource
|
||||
// to ACK/NACK the received resources and request the next set of resources.
|
||||
|
||||
// Service where the sink is the gRPC client. The sink is responsible for
|
||||
// initiating connections and opening streams.
|
||||
service ResourceSource {
|
||||
// The sink, acting as gRPC client, establishes a new resource stream
|
||||
// with the source. The sink sends RequestResources message to
|
||||
// and receives Resources messages from the source.
|
||||
rpc EstablishResourceStream(stream RequestResources) returns (stream Resources) {}
|
||||
}
|
||||
|
||||
// Service where the source is the gRPC client. The source is responsible for
|
||||
// initiating connections and opening streams.
|
||||
service ResourceSink {
|
||||
// The source, acting as gRPC client, establishes a new resource stream
|
||||
// with the sink. The sink sends RequestResources message to and
|
||||
// receives Resources messages from the source.
|
||||
rpc EstablishResourceStream(stream Resources) returns (stream RequestResources) {}
|
||||
}
|
||||
75
istio/src/main/resources/proto/mcp/v1alpha1/metadata.proto
Normal file
75
istio/src/main/resources/proto/mcp/v1alpha1/metadata.proto
Normal file
@ -0,0 +1,75 @@
|
||||
// Copyright 2018 Istio Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package istio.mcp.v1alpha1;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package="istio.io/api/mcp/v1alpha1";
|
||||
option (gogoproto.equal_all) = true;
|
||||
|
||||
// Metadata information that all resources within the Mesh Configuration Protocol must have.
|
||||
message Metadata {
|
||||
// Fully qualified name of the resource. Unique in context of a collection.
|
||||
//
|
||||
// The fully qualified name consists of a directory and basename. The directory identifies
|
||||
// the resources location in a resource hierarchy. The basename identifies the specific
|
||||
// resource name within the context of that directory.
|
||||
//
|
||||
// The directory and basename are composed of one or more segments. Segments must be
|
||||
// valid [DNS labels](https://tools.ietf.org/html/rfc1123). "/" is the delimiter between
|
||||
// segments
|
||||
//
|
||||
// The rightmost segment is the basename. All segments to the
|
||||
// left of the basename form the directory. Segments moving towards the left
|
||||
// represent higher positions in the resource hierarchy, similar to reverse
|
||||
// DNS notation. e.g.
|
||||
//
|
||||
// /<org>/<team>/<subteam>/<resource basename>
|
||||
//
|
||||
// An empty directory indicates a resource that is located at the root of the
|
||||
// hierarchy, e.g.
|
||||
//
|
||||
// /<globally scoped resource>
|
||||
//
|
||||
// On Kubernetes the resource hierarchy is two-levels: namespaces and
|
||||
// cluster-scoped (i.e. global).
|
||||
//
|
||||
// Namespace resources fully qualified name is of the form:
|
||||
//
|
||||
// "<k8s namespace>/<k8s resource name>"
|
||||
//
|
||||
// Cluster scoped resources are located at the root of the hierarchy and are of the form:
|
||||
//
|
||||
// "/<k8s resource name>"
|
||||
string name = 1;
|
||||
|
||||
// The creation timestamp of the resource.
|
||||
google.protobuf.Timestamp create_time = 2;
|
||||
|
||||
// Resource version. This is used to determine when resources change across
|
||||
// resource updates. It should be treated as opaque by consumers/sinks.
|
||||
string version = 3;
|
||||
|
||||
// Map of string keys and values that can be used to organize and categorize
|
||||
// resources within a collection.
|
||||
map<string,string> labels = 4;
|
||||
|
||||
// Map of string keys and values that can be used by source and sink to communicate
|
||||
// arbitrary metadata about this resource.
|
||||
map<string,string> annotations = 5;
|
||||
}
|
||||
35
istio/src/main/resources/proto/mcp/v1alpha1/resource.proto
Normal file
35
istio/src/main/resources/proto/mcp/v1alpha1/resource.proto
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2018 Istio Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
// This package defines the common, core types used by the Mesh Configuration Protocol.
|
||||
package istio.mcp.v1alpha1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
import "mcp/v1alpha1/metadata.proto";
|
||||
|
||||
option go_package="istio.io/api/mcp/v1alpha1";
|
||||
option (gogoproto.equal_all) = true;
|
||||
|
||||
// Resource as transferred via the Mesh Configuration Protocol. Each
|
||||
// resource is made up of common metadata, and a type-specific resource payload.
|
||||
message Resource {
|
||||
// Common metadata describing the resource.
|
||||
istio.mcp.v1alpha1.Metadata metadata = 1;
|
||||
|
||||
// The primary payload for the resource.
|
||||
google.protobuf.Any body = 2;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,803 @@
|
||||
// Copyright Istio Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
import "google/api/field_behavior.proto";
|
||||
import "google/protobuf/struct.proto";
|
||||
import "networking/v1alpha3/sidecar.proto";
|
||||
|
||||
// $schema: istio.networking.v1alpha3.EnvoyFilter
|
||||
// $title: Envoy Filter
|
||||
// $description: Customizing Envoy configuration generated by Istio.
|
||||
// $location: https://istio.io/docs/reference/config/networking/envoy-filter.html
|
||||
// $aliases: [/docs/reference/config/networking/v1alpha3/envoy-filter]
|
||||
|
||||
// `EnvoyFilter` provides a mechanism to customize the Envoy
|
||||
// configuration generated by Istio Pilot. Use EnvoyFilter to modify
|
||||
// values for certain fields, add specific filters, or even add
|
||||
// entirely new listeners, clusters, etc. This feature must be used
|
||||
// with care, as incorrect configurations could potentially
|
||||
// destabilize the entire mesh. Unlike other Istio networking objects,
|
||||
// EnvoyFilters are additively applied. Any number of EnvoyFilters can
|
||||
// exist for a given workload in a specific namespace. The order of
|
||||
// application of these EnvoyFilters is as follows: all EnvoyFilters
|
||||
// in the config [root
|
||||
// namespace](https://istio.io/docs/reference/config/istio.mesh.v1alpha1/#MeshConfig),
|
||||
// followed by all matching EnvoyFilters in the workload's namespace.
|
||||
//
|
||||
// **NOTE 1**: Some aspects of this API is deeply tied to the internal
|
||||
// implementation in Istio networking subsystem as well as Envoy's XDS
|
||||
// API. While the EnvoyFilter API by itself will maintain backward
|
||||
// compatibility, any envoy configuration provided through this
|
||||
// mechanism should be carefully monitored across Istio proxy version
|
||||
// upgrades, to ensure that deprecated fields are removed and replaced
|
||||
// appropriately.
|
||||
//
|
||||
// **NOTE 2**: When multiple EnvoyFilters are bound to the same
|
||||
// workload in a given namespace, all patches will be processed
|
||||
// sequentially in order of creation time. The behavior is undefined
|
||||
// if multiple EnvoyFilter configurations conflict with each other.
|
||||
//
|
||||
// **NOTE 3**: To apply an EnvoyFilter resource to all workloads
|
||||
// (sidecars and gateways) in the system, define the resource in the
|
||||
// config [root
|
||||
// namespace](https://istio.io/docs/reference/config/istio.mesh.v1alpha1/#MeshConfig),
|
||||
// without a workloadSelector.
|
||||
//
|
||||
// The example below declares a global default EnvoyFilter resource in
|
||||
// the root namespace called `istio-config`, that adds a custom
|
||||
// protocol filter on all sidecars in the system, for outbound port
|
||||
// 9307. The filter should be added before the terminating tcp_proxy
|
||||
// filter to take effect. In addition, it sets a 30s idle timeout for
|
||||
// all HTTP connections in both gateways and sidecars.
|
||||
//
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: EnvoyFilter
|
||||
// metadata:
|
||||
// name: custom-protocol
|
||||
// namespace: istio-config # as defined in meshConfig resource.
|
||||
// spec:
|
||||
// configPatches:
|
||||
// - applyTo: NETWORK_FILTER
|
||||
// match:
|
||||
// context: SIDECAR_OUTBOUND # will match outbound listeners in all sidecars
|
||||
// listener:
|
||||
// portNumber: 9307
|
||||
// filterChain:
|
||||
// filter:
|
||||
// name: "envoy.filters.network.tcp_proxy"
|
||||
// patch:
|
||||
// operation: INSERT_BEFORE
|
||||
// value:
|
||||
// # This is the full filter config including the name and config or typed_config section.
|
||||
// name: "envoy.config.filter.network.custom_protocol"
|
||||
// config:
|
||||
// ...
|
||||
// - applyTo: NETWORK_FILTER # http connection manager is a filter in Envoy
|
||||
// match:
|
||||
// # context omitted so that this applies to both sidecars and gateways
|
||||
// listener:
|
||||
// filterChain:
|
||||
// filter:
|
||||
// name: "envoy.filters.network.http_connection_manager"
|
||||
// patch:
|
||||
// operation: MERGE
|
||||
// value:
|
||||
// name: "envoy.filters.network.http_connection_manager"
|
||||
// typed_config:
|
||||
// "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager"
|
||||
// common_http_protocol_options:
|
||||
// idle_timeout: 30s
|
||||
//```
|
||||
//
|
||||
// The following example enables Envoy's Lua filter for all inbound
|
||||
// HTTP calls arriving at service port 8080 of the reviews service pod
|
||||
// with labels "app: reviews", in the bookinfo namespace. The lua
|
||||
// filter calls out to an external service internal.org.net:8888 that
|
||||
// requires a special cluster definition in envoy. The cluster is also
|
||||
// added to the sidecar as part of this configuration.
|
||||
//
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: EnvoyFilter
|
||||
// metadata:
|
||||
// name: reviews-lua
|
||||
// namespace: bookinfo
|
||||
// spec:
|
||||
// workloadSelector:
|
||||
// labels:
|
||||
// app: reviews
|
||||
// configPatches:
|
||||
// # The first patch adds the lua filter to the listener/http connection manager
|
||||
// - applyTo: HTTP_FILTER
|
||||
// match:
|
||||
// context: SIDECAR_INBOUND
|
||||
// listener:
|
||||
// portNumber: 8080
|
||||
// patch:
|
||||
// operation: ADD
|
||||
// filterClass: AUTHZ # This filter will run *after* the Istio authz filter.
|
||||
// value: # lua filter specification
|
||||
// name: envoy.filters.http.lua
|
||||
// typed_config:
|
||||
// "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
|
||||
// inlineCode: |
|
||||
// function envoy_on_request(request_handle)
|
||||
// -- Make an HTTP call to an upstream host with the following headers, body, and timeout.
|
||||
// local headers, body = request_handle:httpCall(
|
||||
// "lua_cluster",
|
||||
// {
|
||||
// [":method"] = "POST",
|
||||
// [":path"] = "/acl",
|
||||
// [":authority"] = "internal.org.net"
|
||||
// },
|
||||
// "authorize call",
|
||||
// 5000)
|
||||
// end
|
||||
// # The second patch adds the cluster that is referenced by the lua code
|
||||
// # cds match is omitted as a new cluster is being added
|
||||
// - applyTo: CLUSTER
|
||||
// match:
|
||||
// context: SIDECAR_OUTBOUND
|
||||
// patch:
|
||||
// operation: ADD
|
||||
// value: # cluster specification
|
||||
// name: "lua_cluster"
|
||||
// type: STRICT_DNS
|
||||
// connect_timeout: 0.5s
|
||||
// lb_policy: ROUND_ROBIN
|
||||
// hosts:
|
||||
// - socket_address:
|
||||
// protocol: TCP
|
||||
// address: "internal.org.net"
|
||||
// port_value: 8888
|
||||
//
|
||||
// ```
|
||||
//
|
||||
// The following example overwrites certain fields (HTTP idle timeout
|
||||
// and X-Forward-For trusted hops) in the HTTP connection manager in a
|
||||
// listener on the ingress gateway in istio-system namespace for the
|
||||
// SNI host app.example.com:
|
||||
//
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: EnvoyFilter
|
||||
// metadata:
|
||||
// name: hcm-tweaks
|
||||
// namespace: istio-system
|
||||
// spec:
|
||||
// workloadSelector:
|
||||
// labels:
|
||||
// istio: ingressgateway
|
||||
// configPatches:
|
||||
// - applyTo: NETWORK_FILTER # http connection manager is a filter in Envoy
|
||||
// match:
|
||||
// context: GATEWAY
|
||||
// listener:
|
||||
// filterChain:
|
||||
// sni: app.example.com
|
||||
// filter:
|
||||
// name: "envoy.filters.network.http_connection_manager"
|
||||
// patch:
|
||||
// operation: MERGE
|
||||
// value:
|
||||
// common_http_protocol_options:
|
||||
// idle_timeout: 30s
|
||||
// xff_num_trusted_hops: 5
|
||||
//```
|
||||
//
|
||||
// The following example inserts an attributegen filter
|
||||
// that produces `istio_operationId` attribute which is consumed
|
||||
// by the istio.stats fiter. `filterClass: STATS` encodes this dependency.
|
||||
//
|
||||
//
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: EnvoyFilter
|
||||
// metadata:
|
||||
// name: reviews-request-operation
|
||||
// namespace: myns
|
||||
// spec:
|
||||
// workloadSelector:
|
||||
// labels:
|
||||
// app: reviews
|
||||
// configPatches:
|
||||
// - applyTo: HTTP_FILTER
|
||||
// match:
|
||||
// context: SIDECAR_INBOUND
|
||||
// patch:
|
||||
// operation: ADD
|
||||
// filterClass: STATS # This filter will run *before* the Istio stats filter.
|
||||
// value:
|
||||
// name: istio.request_operation
|
||||
// typed_config:
|
||||
// "@type": type.googleapis.com/udpa.type.v1.TypedStruct
|
||||
// type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
|
||||
// value:
|
||||
// config:
|
||||
// configuration: |
|
||||
// {
|
||||
// "attributes": [
|
||||
// {
|
||||
// "output_attribute": "istio_operationId",
|
||||
// "match": [
|
||||
// {
|
||||
// "value": "ListReviews",
|
||||
// "condition": "request.url_path == '/reviews' && request.method == 'GET'"
|
||||
// }]
|
||||
// }]
|
||||
// }
|
||||
// vm_config:
|
||||
// runtime: envoy.wasm.runtime.null
|
||||
// code:
|
||||
// local: { inline_string: "envoy.wasm.attributegen" }
|
||||
// ```
|
||||
//
|
||||
// The following example inserts an http ext_authz filter in the `myns` namespace.
|
||||
//
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: EnvoyFilter
|
||||
// metadata:
|
||||
// name: myns-ext-authz
|
||||
// namespace: myns
|
||||
// spec:
|
||||
// configPatches:
|
||||
// - applyTo: HTTP_FILTER
|
||||
// match:
|
||||
// context: SIDECAR_INBOUND
|
||||
// patch:
|
||||
// operation: ADD
|
||||
// filterClass: AUTHZ # This filter will run *after* the Istio authz filter.
|
||||
// value:
|
||||
// name: envoy.filters.http.ext_authz
|
||||
// typed_config:
|
||||
// "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
|
||||
// grpc_service:
|
||||
// envoy_grpc:
|
||||
// cluster_name: acme-ext-authz
|
||||
// initial_metadata:
|
||||
// - key: foo
|
||||
// value: myauth.acme # required by local ext auth server.
|
||||
// ```
|
||||
//
|
||||
// A workload in the `myns` namespace needs to access a different ext_auth server
|
||||
// that does not accept initial metadata. Since proto merge cannot remove fields, the
|
||||
// following configuration uses the `REPLACE` operation. If you do not need to inherit
|
||||
// fields, REPLACE is preferred over MERGE.
|
||||
//
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: EnvoyFilter
|
||||
// metadata:
|
||||
// name: mysvc-ext-authz
|
||||
// namespace: myns
|
||||
// spec:
|
||||
// workloadSelector:
|
||||
// labels:
|
||||
// app: mysvc
|
||||
// configPatches:
|
||||
// - applyTo: HTTP_FILTER
|
||||
// match:
|
||||
// context: SIDECAR_INBOUND
|
||||
// patch:
|
||||
// operation: REPLACE
|
||||
// value:
|
||||
// name: envoy.filters.http.ext_authz
|
||||
// typed_config:
|
||||
// "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
|
||||
// grpc_service:
|
||||
// envoy_grpc:
|
||||
// cluster_name: acme-ext-authz-alt
|
||||
// ```
|
||||
//
|
||||
// The following example deploys a Wasm extension for all inbound sidecar HTTP requests.
|
||||
//
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: EnvoyFilter
|
||||
// metadata:
|
||||
// name: wasm-example
|
||||
// namespace: myns
|
||||
// spec:
|
||||
// configPatches:
|
||||
// # The first patch defines a named Wasm extension and provides a URL to fetch Wasm binary from,
|
||||
// # and the binary configuration. It should come before the next patch that applies it.
|
||||
// # This resource is visible to all proxies in the namespace "myns". It is possible to provide
|
||||
// # multiple definitions for the same name "my-wasm-extension" in multiple namespaces. We recommend that:
|
||||
// # - if overriding is desired, then the root level definition can be overriden per namespace with REPLACE.
|
||||
// # - if overriding is not desired, then the name should be qualified with the namespace "myns/my-wasm-extension",
|
||||
// # to avoid accidental name collisions.
|
||||
// - applyTo: EXTENSION_CONFIG
|
||||
// patch:
|
||||
// operation: ADD # REPLACE is also supported, and would override a cluster level resource with the same name.
|
||||
// value:
|
||||
// name: my-wasm-extension
|
||||
// typed_config:
|
||||
// "@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
|
||||
// config:
|
||||
// root_id: my-wasm-root-id
|
||||
// vm_config:
|
||||
// vm_id: my-wasm-vm-id
|
||||
// runtime: envoy.wasm.runtime.v8
|
||||
// code:
|
||||
// remote:
|
||||
// http_uri:
|
||||
// uri: http://my-wasm-binary-uri
|
||||
// configuration: |
|
||||
// {}
|
||||
// # The second patch instructs to apply the above Wasm filter to the listener/http connection manager.
|
||||
// - applyTo: HTTP_FILTER
|
||||
// match:
|
||||
// context: SIDECAR_INBOUND
|
||||
// patch:
|
||||
// operation: ADD
|
||||
// filterClass: AUTHZ # This filter will run *after* the Istio authz filter.
|
||||
// value:
|
||||
// name: my-wasm-extension # This must match the name above
|
||||
// config_discovery:
|
||||
// config_source:
|
||||
// api_config_source:
|
||||
// api_type: GRPC
|
||||
// transport_api_version: V3
|
||||
// grpc_services:
|
||||
// - envoy_grpc:
|
||||
// cluster_name: xds-grpc
|
||||
// type_urls: ["envoy.extensions.filters.http.wasm.v3.Wasm"]
|
||||
// ```
|
||||
|
||||
package istio.networking.v1alpha3;
|
||||
|
||||
option go_package = "istio.io/api/networking/v1alpha3";
|
||||
|
||||
// EnvoyFilter provides a mechanism to customize the Envoy configuration
|
||||
// generated by Istio Pilot.
|
||||
//
|
||||
// <!-- crd generation tags
|
||||
// +cue-gen:EnvoyFilter:groupName:networking.istio.io
|
||||
// +cue-gen:EnvoyFilter:version:v1alpha3
|
||||
// +cue-gen:EnvoyFilter:storageVersion
|
||||
// +cue-gen:EnvoyFilter:annotations:helm.sh/resource-policy=keep
|
||||
// +cue-gen:EnvoyFilter:labels:app=istio-pilot,chart=istio,heritage=Tiller,release=istio
|
||||
// +cue-gen:EnvoyFilter:subresource:status
|
||||
// +cue-gen:EnvoyFilter:scope:Namespaced
|
||||
// +cue-gen:EnvoyFilter:resource:categories=istio-io,networking-istio-io
|
||||
// +cue-gen:EnvoyFilter:preserveUnknownFields:true
|
||||
// -->
|
||||
//
|
||||
// <!-- go code generation tags
|
||||
// +kubetype-gen
|
||||
// +kubetype-gen:groupVersion=networking.istio.io/v1alpha3
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen=true
|
||||
// -->
|
||||
message EnvoyFilter {
|
||||
// `ApplyTo` specifies where in the Envoy configuration, the given patch should be applied.
|
||||
enum ApplyTo {
|
||||
|
||||
INVALID = 0;
|
||||
|
||||
// Applies the patch to the listener.
|
||||
LISTENER = 1;
|
||||
|
||||
// Applies the patch to the filter chain.
|
||||
FILTER_CHAIN = 2;
|
||||
|
||||
// Applies the patch to the network filter chain, to modify an
|
||||
// existing filter or add a new filter.
|
||||
NETWORK_FILTER = 3;
|
||||
|
||||
// Applies the patch to the HTTP filter chain in the http
|
||||
// connection manager, to modify an existing filter or add a new
|
||||
// filter.
|
||||
HTTP_FILTER = 4;
|
||||
|
||||
// Applies the patch to the Route configuration (rds output)
|
||||
// inside a HTTP connection manager. This does not apply to the
|
||||
// virtual host. Currently, only `MERGE` operation is allowed on the
|
||||
// route configuration objects.
|
||||
ROUTE_CONFIGURATION = 5;
|
||||
|
||||
// Applies the patch to a virtual host inside a route configuration.
|
||||
VIRTUAL_HOST = 6;
|
||||
|
||||
// Applies the patch to a route object inside the matched virtual
|
||||
// host in a route configuration.
|
||||
HTTP_ROUTE = 7;
|
||||
|
||||
// Applies the patch to a cluster in a CDS output. Also used to add new clusters.
|
||||
CLUSTER = 8;
|
||||
|
||||
// Applies the patch to or adds an extension config in ECDS output. Note that ECDS
|
||||
// is only supported by HTTP filters.
|
||||
EXTENSION_CONFIG = 9;
|
||||
};
|
||||
|
||||
// PatchContext selects a class of configurations based on the
|
||||
// traffic flow direction and workload type.
|
||||
enum PatchContext {
|
||||
// All listeners/routes/clusters in both sidecars and gateways.
|
||||
ANY = 0;
|
||||
|
||||
// Inbound listener/route/cluster in sidecar.
|
||||
SIDECAR_INBOUND = 1;
|
||||
|
||||
// Outbound listener/route/cluster in sidecar.
|
||||
SIDECAR_OUTBOUND = 2;
|
||||
|
||||
// Gateway listener/route/cluster.
|
||||
GATEWAY = 3;
|
||||
};
|
||||
|
||||
// One or more properties of the proxy to match on.
|
||||
message ProxyMatch {
|
||||
// A regular expression in golang regex format (RE2) that can be
|
||||
// used to select proxies using a specific version of istio
|
||||
// proxy. The Istio version for a given proxy is obtained from the
|
||||
// node metadata field `ISTIO_VERSION` supplied by the proxy when
|
||||
// connecting to Pilot. This value is embedded as an environment
|
||||
// variable (`ISTIO_META_ISTIO_VERSION`) in the Istio proxy docker
|
||||
// image. Custom proxy implementations should provide this metadata
|
||||
// variable to take advantage of the Istio version check option.
|
||||
string proxy_version = 1;
|
||||
|
||||
// Match on the node metadata supplied by a proxy when connecting
|
||||
// to Istio Pilot. Note that while Envoy's node metadata is of
|
||||
// type Struct, only string key-value pairs are processed by
|
||||
// Pilot. All keys specified in the metadata must match with exact
|
||||
// values. The match will fail if any of the specified keys are
|
||||
// absent or the values fail to match.
|
||||
map<string, string> metadata = 2;
|
||||
};
|
||||
|
||||
// Conditions specified in `ClusterMatch` must be met for the patch
|
||||
// to be applied to a cluster.
|
||||
message ClusterMatch {
|
||||
// The service port for which this cluster was generated. If
|
||||
// omitted, applies to clusters for any port.
|
||||
uint32 port_number = 1;
|
||||
|
||||
// The fully qualified service name for this cluster. If omitted,
|
||||
// applies to clusters for any service. For services defined
|
||||
// through service entries, the service name is same as the hosts
|
||||
// defined in the service entry.
|
||||
string service = 2;
|
||||
|
||||
// The subset associated with the service. If omitted, applies to
|
||||
// clusters for any subset of a service.
|
||||
string subset = 3;
|
||||
|
||||
// The exact name of the cluster to match. To match a specific
|
||||
// cluster by name, such as the internally generated `Passthrough`
|
||||
// cluster, leave all fields in clusterMatch empty, except the
|
||||
// name.
|
||||
string name = 4;
|
||||
};
|
||||
|
||||
// Conditions specified in RouteConfigurationMatch must be met for
|
||||
// the patch to be applied to a route configuration object or a
|
||||
// specific virtual host within the route configuration.
|
||||
message RouteConfigurationMatch {
|
||||
// Match a specific route inside a virtual host in a route configuration.
|
||||
message RouteMatch {
|
||||
// The Route objects generated by default are named as
|
||||
// default. Route objects generated using a virtual service
|
||||
// will carry the name used in the virtual service's HTTP
|
||||
// routes.
|
||||
string name = 1;
|
||||
|
||||
// Action refers to the route action taken by Envoy when a http route matches.
|
||||
enum Action {
|
||||
// All three route actions
|
||||
ANY = 0;
|
||||
// Route traffic to a cluster / weighted clusters.
|
||||
ROUTE = 1;
|
||||
// Redirect request.
|
||||
REDIRECT = 2;
|
||||
// directly respond to a request with specific payload.
|
||||
DIRECT_RESPONSE = 3;
|
||||
};
|
||||
|
||||
// Match a route with specific action type.
|
||||
Action action = 2;
|
||||
}
|
||||
|
||||
// Match a specific virtual host inside a route configuration.
|
||||
message VirtualHostMatch {
|
||||
// The VirtualHosts objects generated by Istio are named as
|
||||
// host:port, where the host typically corresponds to the
|
||||
// VirtualService's host field or the hostname of a service in the
|
||||
// registry.
|
||||
string name = 1;
|
||||
|
||||
// Match a specific route within the virtual host.
|
||||
RouteMatch route = 2;
|
||||
}
|
||||
|
||||
// The service port number or gateway server port number for which
|
||||
// this route configuration was generated. If omitted, applies to
|
||||
// route configurations for all ports.
|
||||
uint32 port_number = 1;
|
||||
|
||||
// Applicable only for GATEWAY context. The gateway server port
|
||||
// name for which this route configuration was generated.
|
||||
string port_name = 2;
|
||||
|
||||
// The Istio gateway config's namespace/name for which this route
|
||||
// configuration was generated. Applies only if the context is
|
||||
// GATEWAY. Should be in the namespace/name format. Use this field
|
||||
// in conjunction with the `portNumber` and `portName` to accurately
|
||||
// select the Envoy route configuration for a specific HTTPS
|
||||
// server within a gateway config object.
|
||||
string gateway = 3;
|
||||
|
||||
// Match a specific virtual host in a route configuration and
|
||||
// apply the patch to the virtual host.
|
||||
VirtualHostMatch vhost = 4;
|
||||
|
||||
// Route configuration name to match on. Can be used to match a
|
||||
// specific route configuration by name, such as the internally
|
||||
// generated `http_proxy` route configuration for all sidecars.
|
||||
string name = 5;
|
||||
};
|
||||
|
||||
// Conditions specified in a listener match must be met for the
|
||||
// patch to be applied to a specific listener across all filter
|
||||
// chains, or a specific filter chain inside the listener.
|
||||
message ListenerMatch {
|
||||
// For listeners with multiple filter chains (e.g., inbound
|
||||
// listeners on sidecars with permissive mTLS, gateway listeners
|
||||
// with multiple SNI matches), the filter chain match can be used
|
||||
// to select a specific filter chain to patch.
|
||||
message FilterChainMatch {
|
||||
// The name assigned to the filter chain.
|
||||
string name = 1;
|
||||
|
||||
// The SNI value used by a filter chain's match condition. This
|
||||
// condition will evaluate to false if the filter chain has no
|
||||
// sni match.
|
||||
string sni = 2;
|
||||
|
||||
// Applies only to `SIDECAR_INBOUND` context. If non-empty, a
|
||||
// transport protocol to consider when determining a filter
|
||||
// chain match. This value will be compared against the
|
||||
// transport protocol of a new connection, when it's detected by
|
||||
// the `tls_inspector` listener filter.
|
||||
//
|
||||
// Accepted values include:
|
||||
//
|
||||
// * `raw_buffer` - default, used when no transport protocol is detected.
|
||||
// * `tls` - set when TLS protocol is detected by the TLS inspector.
|
||||
string transport_protocol = 3;
|
||||
|
||||
// Applies only to sidecars. If non-empty, a comma separated set
|
||||
// of application protocols to consider when determining a
|
||||
// filter chain match. This value will be compared against the
|
||||
// application protocols of a new connection, when it's detected
|
||||
// by one of the listener filters such as the `http_inspector`.
|
||||
//
|
||||
// Accepted values include: h2, http/1.1, http/1.0
|
||||
string application_protocols = 4;
|
||||
|
||||
// The name of a specific filter to apply the patch to. Set this
|
||||
// to `envoy.filters.network.http_connection_manager` to add a filter or apply a
|
||||
// patch to the HTTP connection manager.
|
||||
FilterMatch filter = 5;
|
||||
};
|
||||
|
||||
// Conditions to match a specific filter within a filter chain.
|
||||
message FilterMatch {
|
||||
// The filter name to match on.
|
||||
// For standard Envoy filters, [canonical filter](https://www.envoyproxy.io/docs/envoy/latest/version_history/v1.14.0#deprecated)
|
||||
// names should be used.
|
||||
string name = 1;
|
||||
// The next level filter within this filter to match
|
||||
// upon. Typically used for HTTP Connection Manager filters and
|
||||
// Thrift filters.
|
||||
SubFilterMatch sub_filter = 2;
|
||||
};
|
||||
|
||||
// Conditions to match a specific filter within another
|
||||
// filter. This field is typically useful to match a HTTP filter
|
||||
// inside the `envoy.filters.network.http_connection_manager` network filter.
|
||||
// This could also be applicable for thrift filters.
|
||||
message SubFilterMatch {
|
||||
// The filter name to match on.
|
||||
string name = 1;
|
||||
};
|
||||
|
||||
// The service port/gateway port to which traffic is being
|
||||
// sent/received. If not specified, matches all listeners. Even though
|
||||
// inbound listeners are generated for the instance/pod ports, only
|
||||
// service ports should be used to match listeners.
|
||||
uint32 port_number = 1;
|
||||
|
||||
// Instead of using specific port numbers, a set of ports matching
|
||||
// a given service's port name can be selected. Matching is case
|
||||
// insensitive.
|
||||
// Not implemented.
|
||||
// $hide_from_docs
|
||||
string port_name = 2;
|
||||
|
||||
// Match a specific filter chain in a listener. If specified, the
|
||||
// patch will be applied to the filter chain (and a specific
|
||||
// filter if specified) and not to other filter chains in the
|
||||
// listener.
|
||||
FilterChainMatch filter_chain = 3;
|
||||
|
||||
// Match a specific listener by its name. The listeners generated
|
||||
// by Pilot are typically named as IP:Port.
|
||||
string name = 4;
|
||||
};
|
||||
|
||||
// Patch specifies how the selected object should be modified.
|
||||
message Patch {
|
||||
|
||||
// Operation denotes how the patch should be applied to the selected
|
||||
// configuration.
|
||||
enum Operation {
|
||||
INVALID = 0;
|
||||
|
||||
// Merge the provided config with the generated config using
|
||||
// proto merge semantics. If you are specifying config in its
|
||||
// entirity, use `REPLACE` instead.
|
||||
MERGE = 1;
|
||||
|
||||
// Add the provided config to an existing list (of listeners,
|
||||
// clusters, virtual hosts, network filters, or http
|
||||
// filters). This operation will be ignored when `applyTo` is set
|
||||
// to `ROUTE_CONFIGURATION`, or `HTTP_ROUTE`.
|
||||
ADD = 2;
|
||||
|
||||
// Remove the selected object from the list (of listeners,
|
||||
// clusters, virtual hosts, network filters, routes, or http
|
||||
// filters). Does not require a value to be specified. This
|
||||
// operation will be ignored when `applyTo` is set to
|
||||
// `ROUTE_CONFIGURATION`, or `HTTP_ROUTE`.
|
||||
REMOVE = 3;
|
||||
|
||||
// Insert operation on an array of named objects. This operation
|
||||
// is typically useful only in the context of filters or routes,
|
||||
// where the order of elements matter. Routes should be ordered
|
||||
// based on most to least specific matching criteria since the
|
||||
// first matching element is selected. For clusters and virtual hosts,
|
||||
// order of the element in the array does not matter. Insert
|
||||
// before the selected filter or sub filter. If no filter is
|
||||
// selected, the specified filter will be inserted at the front
|
||||
// of the list.
|
||||
INSERT_BEFORE = 4;
|
||||
|
||||
// Insert operation on an array of named objects. This operation
|
||||
// is typically useful only in the context of filters or routes,
|
||||
// where the order of elements matter. Routes should be ordered
|
||||
// based on most to least specific matching criteria since the
|
||||
// first matching element is selected. For clusters and virtual hosts,
|
||||
// order of the element in the array does not matter. Insert
|
||||
// after the selected filter or sub filter. If no filter is
|
||||
// selected, the specified filter will be inserted at the end
|
||||
// of the list.
|
||||
INSERT_AFTER = 5;
|
||||
|
||||
// Insert operation on an array of named objects. This operation
|
||||
// is typically useful only in the context of filters or routes,
|
||||
// where the order of elements matter. Routes should be ordered
|
||||
// based on most to least specific matching criteria since the
|
||||
// first matching element is selected. For clusters and virtual hosts,
|
||||
// order of the element in the array does not matter. Insert
|
||||
// first in the list based on the presence of selected filter or not.
|
||||
// This is specifically useful when you want your filter first in the
|
||||
// list based on a match condition specified in Match clause.
|
||||
INSERT_FIRST = 6;
|
||||
|
||||
// Replace contents of a named filter with new contents.
|
||||
// `REPLACE` operation is only valid for `HTTP_FILTER` and
|
||||
// `NETWORK_FILTER`. If the named filter is not found, this operation
|
||||
// has no effect.
|
||||
REPLACE = 7;
|
||||
}
|
||||
|
||||
// Determines how the patch should be applied.
|
||||
Operation operation = 1;
|
||||
|
||||
// The JSON config of the object being patched. This will be merged using
|
||||
// proto merge semantics with the existing proto in the path.
|
||||
google.protobuf.Struct value = 2;
|
||||
|
||||
// FilterClass determines the filter insertion point in the filter chain
|
||||
// relative to the filters implicitly inserted by the control plane.
|
||||
// It is used in conjuction with the `ADD` operation.
|
||||
// This is the preferred insertion mechanism for adding filters over
|
||||
// the `INSERT_*` operations since those operations rely on potentially unstable
|
||||
// filter names.
|
||||
// Filter ordering is important if your filter depends on or affects the
|
||||
// functioning of a another filter in the filter chain.
|
||||
// Within a filter class, filters are inserted in the order of processing.
|
||||
enum FilterClass {
|
||||
// Control plane decides where to insert the filter.
|
||||
// Do not specify `FilterClass` if the filter is independent of others.
|
||||
UNSPECIFIED = 0;
|
||||
|
||||
// Insert filter after Istio authentication filters.
|
||||
AUTHN = 1;
|
||||
|
||||
// Insert filter after Istio authorization filters.
|
||||
AUTHZ = 2;
|
||||
|
||||
// Insert filter before Istio stats filters.
|
||||
STATS = 3;
|
||||
};
|
||||
|
||||
// Determines the filter insertion order.
|
||||
FilterClass filter_class = 3;
|
||||
};
|
||||
|
||||
// One or more match conditions to be met before a patch is applied
|
||||
// to the generated configuration for a given proxy.
|
||||
message EnvoyConfigObjectMatch {
|
||||
// The specific config generation context to match on. Istio Pilot
|
||||
// generates envoy configuration in the context of a gateway,
|
||||
// inbound traffic to sidecar and outbound traffic from sidecar.
|
||||
PatchContext context = 1;
|
||||
|
||||
// Match on properties associated with a proxy.
|
||||
ProxyMatch proxy = 2;
|
||||
|
||||
oneof object_types {
|
||||
// Match on envoy listener attributes.
|
||||
ListenerMatch listener = 3;
|
||||
// Match on envoy HTTP route configuration attributes.
|
||||
RouteConfigurationMatch route_configuration = 4;
|
||||
// Match on envoy cluster attributes.
|
||||
ClusterMatch cluster = 5;
|
||||
}
|
||||
};
|
||||
|
||||
// Changes to be made to various envoy config objects.
|
||||
message EnvoyConfigObjectPatch {
|
||||
// Specifies where in the Envoy configuration, the patch should be
|
||||
// applied. The match is expected to select the appropriate
|
||||
// object based on applyTo. For example, an applyTo with
|
||||
// `HTTP_FILTER` is expected to have a match condition on the
|
||||
// listeners, with a network filter selection on
|
||||
// `envoy.filters.network.http_connection_manager` and a sub filter selection on the
|
||||
// HTTP filter relative to which the insertion should be
|
||||
// performed. Similarly, an applyTo on `CLUSTER` should have a match
|
||||
// (if provided) on the cluster and not on a listener.
|
||||
ApplyTo apply_to = 1;
|
||||
|
||||
// Match on listener/route configuration/cluster.
|
||||
EnvoyConfigObjectMatch match = 2;
|
||||
|
||||
// The patch to apply along with the operation.
|
||||
Patch patch = 3;
|
||||
}
|
||||
|
||||
reserved 1, 2;
|
||||
reserved "filters", "workload_labels";
|
||||
|
||||
// Criteria used to select the specific set of pods/VMs on which
|
||||
// this patch configuration should be applied. If omitted, the set
|
||||
// of patches in this configuration will be applied to all workload
|
||||
// instances in the same namespace. If omitted, the `EnvoyFilter`
|
||||
// patches will be applied to all workloads in the same
|
||||
// namespace. If the `EnvoyFilter` is present in the config root
|
||||
// namespace, it will be applied to all applicable workloads in any
|
||||
// namespace.
|
||||
WorkloadSelector workload_selector = 3;
|
||||
|
||||
// One or more patches with match conditions.
|
||||
repeated EnvoyConfigObjectPatch config_patches = 4 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
729
istio/src/main/resources/proto/networking/v1alpha3/gateway.proto
Normal file
729
istio/src/main/resources/proto/networking/v1alpha3/gateway.proto
Normal file
@ -0,0 +1,729 @@
|
||||
// Copyright 2017 Istio Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
import "google/api/field_behavior.proto";
|
||||
|
||||
// $schema: istio.networking.v1alpha3.Gateway
|
||||
// $title: Gateway
|
||||
// $description: Configuration affecting edge load balancer.
|
||||
// $location: https://istio.io/docs/reference/config/networking/gateway.html
|
||||
// $aliases: [/docs/reference/config/networking/v1alpha3/gateway]
|
||||
|
||||
// `Gateway` describes a load balancer operating at the edge of the mesh
|
||||
// receiving incoming or outgoing HTTP/TCP connections. The specification
|
||||
// describes a set of ports that should be exposed, the type of protocol to
|
||||
// use, SNI configuration for the load balancer, etc.
|
||||
//
|
||||
// For example, the following Gateway configuration sets up a proxy to act
|
||||
// as a load balancer exposing port 80 and 9080 (http), 443 (https),
|
||||
// 9443(https) and port 2379 (TCP) for ingress. The gateway will be
|
||||
// applied to the proxy running on a pod with labels `app:
|
||||
// my-gateway-controller`. While Istio will configure the proxy to listen
|
||||
// on these ports, it is the responsibility of the user to ensure that
|
||||
// external traffic to these ports are allowed into the mesh.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: Gateway
|
||||
// metadata:
|
||||
// name: my-gateway
|
||||
// namespace: some-config-namespace
|
||||
// spec:
|
||||
// selector:
|
||||
// app: my-gateway-controller
|
||||
// servers:
|
||||
// - port:
|
||||
// number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// hosts:
|
||||
// - uk.bookinfo.com
|
||||
// - eu.bookinfo.com
|
||||
// tls:
|
||||
// httpsRedirect: true # sends 301 redirect for http requests
|
||||
// - port:
|
||||
// number: 443
|
||||
// name: https-443
|
||||
// protocol: HTTPS
|
||||
// hosts:
|
||||
// - uk.bookinfo.com
|
||||
// - eu.bookinfo.com
|
||||
// tls:
|
||||
// mode: SIMPLE # enables HTTPS on this port
|
||||
// serverCertificate: /etc/certs/servercert.pem
|
||||
// privateKey: /etc/certs/privatekey.pem
|
||||
// - port:
|
||||
// number: 9443
|
||||
// name: https-9443
|
||||
// protocol: HTTPS
|
||||
// hosts:
|
||||
// - "bookinfo-namespace/*.bookinfo.com"
|
||||
// tls:
|
||||
// mode: SIMPLE # enables HTTPS on this port
|
||||
// credentialName: bookinfo-secret # fetches certs from Kubernetes secret
|
||||
// - port:
|
||||
// number: 9080
|
||||
// name: http-wildcard
|
||||
// protocol: HTTP
|
||||
// hosts:
|
||||
// - "*"
|
||||
// - port:
|
||||
// number: 2379 # to expose internal service via external port 2379
|
||||
// name: mongo
|
||||
// protocol: MONGO
|
||||
// hosts:
|
||||
// - "*"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: Gateway
|
||||
// metadata:
|
||||
// name: my-gateway
|
||||
// namespace: some-config-namespace
|
||||
// spec:
|
||||
// selector:
|
||||
// app: my-gateway-controller
|
||||
// servers:
|
||||
// - port:
|
||||
// number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// hosts:
|
||||
// - uk.bookinfo.com
|
||||
// - eu.bookinfo.com
|
||||
// tls:
|
||||
// httpsRedirect: true # sends 301 redirect for http requests
|
||||
// - port:
|
||||
// number: 443
|
||||
// name: https-443
|
||||
// protocol: HTTPS
|
||||
// hosts:
|
||||
// - uk.bookinfo.com
|
||||
// - eu.bookinfo.com
|
||||
// tls:
|
||||
// mode: SIMPLE # enables HTTPS on this port
|
||||
// serverCertificate: /etc/certs/servercert.pem
|
||||
// privateKey: /etc/certs/privatekey.pem
|
||||
// - port:
|
||||
// number: 9443
|
||||
// name: https-9443
|
||||
// protocol: HTTPS
|
||||
// hosts:
|
||||
// - "bookinfo-namespace/*.bookinfo.com"
|
||||
// tls:
|
||||
// mode: SIMPLE # enables HTTPS on this port
|
||||
// credentialName: bookinfo-secret # fetches certs from Kubernetes secret
|
||||
// - port:
|
||||
// number: 9080
|
||||
// name: http-wildcard
|
||||
// protocol: HTTP
|
||||
// hosts:
|
||||
// - "*"
|
||||
// - port:
|
||||
// number: 2379 # to expose internal service via external port 2379
|
||||
// name: mongo
|
||||
// protocol: MONGO
|
||||
// hosts:
|
||||
// - "*"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// The Gateway specification above describes the L4-L6 properties of a load
|
||||
// balancer. A `VirtualService` can then be bound to a gateway to control
|
||||
// the forwarding of traffic arriving at a particular host or gateway port.
|
||||
//
|
||||
// For example, the following VirtualService splits traffic for
|
||||
// `https://uk.bookinfo.com/reviews`, `https://eu.bookinfo.com/reviews`,
|
||||
// `http://uk.bookinfo.com:9080/reviews`,
|
||||
// `http://eu.bookinfo.com:9080/reviews` into two versions (prod and qa) of
|
||||
// an internal reviews service on port 9080. In addition, requests
|
||||
// containing the cookie "user: dev-123" will be sent to special port 7777
|
||||
// in the qa version. The same rule is also applicable inside the mesh for
|
||||
// requests to the "reviews.prod.svc.cluster.local" service. This rule is
|
||||
// applicable across ports 443, 9080. Note that `http://uk.bookinfo.com`
|
||||
// gets redirected to `https://uk.bookinfo.com` (i.e. 80 redirects to 443).
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: VirtualService
|
||||
// metadata:
|
||||
// name: bookinfo-rule
|
||||
// namespace: bookinfo-namespace
|
||||
// spec:
|
||||
// hosts:
|
||||
// - reviews.prod.svc.cluster.local
|
||||
// - uk.bookinfo.com
|
||||
// - eu.bookinfo.com
|
||||
// gateways:
|
||||
// - some-config-namespace/my-gateway
|
||||
// - mesh # applies to all the sidecars in the mesh
|
||||
// http:
|
||||
// - match:
|
||||
// - headers:
|
||||
// cookie:
|
||||
// exact: "user=dev-123"
|
||||
// route:
|
||||
// - destination:
|
||||
// port:
|
||||
// number: 7777
|
||||
// host: reviews.qa.svc.cluster.local
|
||||
// - match:
|
||||
// - uri:
|
||||
// prefix: /reviews/
|
||||
// route:
|
||||
// - destination:
|
||||
// port:
|
||||
// number: 9080 # can be omitted if it's the only port for reviews
|
||||
// host: reviews.prod.svc.cluster.local
|
||||
// weight: 80
|
||||
// - destination:
|
||||
// host: reviews.qa.svc.cluster.local
|
||||
// weight: 20
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: VirtualService
|
||||
// metadata:
|
||||
// name: bookinfo-rule
|
||||
// namespace: bookinfo-namespace
|
||||
// spec:
|
||||
// hosts:
|
||||
// - reviews.prod.svc.cluster.local
|
||||
// - uk.bookinfo.com
|
||||
// - eu.bookinfo.com
|
||||
// gateways:
|
||||
// - some-config-namespace/my-gateway
|
||||
// - mesh # applies to all the sidecars in the mesh
|
||||
// http:
|
||||
// - match:
|
||||
// - headers:
|
||||
// cookie:
|
||||
// exact: "user=dev-123"
|
||||
// route:
|
||||
// - destination:
|
||||
// port:
|
||||
// number: 7777
|
||||
// host: reviews.qa.svc.cluster.local
|
||||
// - match:
|
||||
// - uri:
|
||||
// prefix: /reviews/
|
||||
// route:
|
||||
// - destination:
|
||||
// port:
|
||||
// number: 9080 # can be omitted if it's the only port for reviews
|
||||
// host: reviews.prod.svc.cluster.local
|
||||
// weight: 80
|
||||
// - destination:
|
||||
// host: reviews.qa.svc.cluster.local
|
||||
// weight: 20
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// The following VirtualService forwards traffic arriving at (external)
|
||||
// port 27017 to internal Mongo server on port 5555. This rule is not
|
||||
// applicable internally in the mesh as the gateway list omits the
|
||||
// reserved name `mesh`.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: VirtualService
|
||||
// metadata:
|
||||
// name: bookinfo-mongo
|
||||
// namespace: bookinfo-namespace
|
||||
// spec:
|
||||
// hosts:
|
||||
// - mongosvr.prod.svc.cluster.local # name of internal Mongo service
|
||||
// gateways:
|
||||
// - some-config-namespace/my-gateway # can omit the namespace if gateway is in same
|
||||
// namespace as virtual service.
|
||||
// tcp:
|
||||
// - match:
|
||||
// - port: 27017
|
||||
// route:
|
||||
// - destination:
|
||||
// host: mongo.prod.svc.cluster.local
|
||||
// port:
|
||||
// number: 5555
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: VirtualService
|
||||
// metadata:
|
||||
// name: bookinfo-mongo
|
||||
// namespace: bookinfo-namespace
|
||||
// spec:
|
||||
// hosts:
|
||||
// - mongosvr.prod.svc.cluster.local # name of internal Mongo service
|
||||
// gateways:
|
||||
// - some-config-namespace/my-gateway # can omit the namespace if gateway is in same
|
||||
// namespace as virtual service.
|
||||
// tcp:
|
||||
// - match:
|
||||
// - port: 27017
|
||||
// route:
|
||||
// - destination:
|
||||
// host: mongo.prod.svc.cluster.local
|
||||
// port:
|
||||
// number: 5555
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// It is possible to restrict the set of virtual services that can bind to
|
||||
// a gateway server using the namespace/hostname syntax in the hosts field.
|
||||
// For example, the following Gateway allows any virtual service in the ns1
|
||||
// namespace to bind to it, while restricting only the virtual service with
|
||||
// foo.bar.com host in the ns2 namespace to bind to it.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: Gateway
|
||||
// metadata:
|
||||
// name: my-gateway
|
||||
// namespace: some-config-namespace
|
||||
// spec:
|
||||
// selector:
|
||||
// app: my-gateway-controller
|
||||
// servers:
|
||||
// - port:
|
||||
// number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// hosts:
|
||||
// - "ns1/*"
|
||||
// - "ns2/foo.bar.com"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: Gateway
|
||||
// metadata:
|
||||
// name: my-gateway
|
||||
// namespace: some-config-namespace
|
||||
// spec:
|
||||
// selector:
|
||||
// app: my-gateway-controller
|
||||
// servers:
|
||||
// - port:
|
||||
// number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// hosts:
|
||||
// - "ns1/*"
|
||||
// - "ns2/foo.bar.com"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
package istio.networking.v1alpha3;
|
||||
|
||||
option go_package = "istio.io/api/networking/v1alpha3";
|
||||
|
||||
// Gateway describes a load balancer operating at the edge of the mesh
|
||||
// receiving incoming or outgoing HTTP/TCP connections.
|
||||
//
|
||||
// <!-- crd generation tags
|
||||
// +cue-gen:Gateway:groupName:networking.istio.io
|
||||
// +cue-gen:Gateway:version:v1alpha3
|
||||
// +cue-gen:Gateway:storageVersion
|
||||
// +cue-gen:Gateway:annotations:helm.sh/resource-policy=keep
|
||||
// +cue-gen:Gateway:labels:app=istio-pilot,chart=istio,heritage=Tiller,release=istio
|
||||
// +cue-gen:Gateway:subresource:status
|
||||
// +cue-gen:Gateway:scope:Namespaced
|
||||
// +cue-gen:Gateway:resource:categories=istio-io,networking-istio-io,shortNames=gw
|
||||
// +cue-gen:Gateway:preserveUnknownFields:false
|
||||
// -->
|
||||
//
|
||||
// <!-- go code generation tags
|
||||
// +kubetype-gen
|
||||
// +kubetype-gen:groupVersion=networking.istio.io/v1alpha3
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen=true
|
||||
// -->
|
||||
message Gateway {
|
||||
// A list of server specifications.
|
||||
repeated Server servers = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// One or more labels that indicate a specific set of pods/VMs
|
||||
// on which this gateway configuration should be applied.
|
||||
// By default workloads are searched across all namespaces based on label selectors.
|
||||
// This implies that a gateway resource in the namespace "foo" can select pods in
|
||||
// the namespace "bar" based on labels.
|
||||
// This behavior can be controlled via the `PILOT_SCOPE_GATEWAY_TO_NAMESPACE`
|
||||
// environment variable in istiod. If this variable is set
|
||||
// to true, the scope of label search is restricted to the configuration
|
||||
// namespace in which the the resource is present. In other words, the Gateway
|
||||
// resource must reside in the same namespace as the gateway workload
|
||||
// instance.
|
||||
// If selector is nil, the Gateway will be applied to all workloads.
|
||||
map<string, string> selector = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
}
|
||||
|
||||
// `Server` describes the properties of the proxy on a given load balancer
|
||||
// port. For example,
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: Gateway
|
||||
// metadata:
|
||||
// name: my-ingress
|
||||
// spec:
|
||||
// selector:
|
||||
// app: my-ingressgateway
|
||||
// servers:
|
||||
// - port:
|
||||
// number: 80
|
||||
// name: http2
|
||||
// protocol: HTTP2
|
||||
// hosts:
|
||||
// - "*"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: Gateway
|
||||
// metadata:
|
||||
// name: my-ingress
|
||||
// spec:
|
||||
// selector:
|
||||
// app: my-ingressgateway
|
||||
// servers:
|
||||
// - port:
|
||||
// number: 80
|
||||
// name: http2
|
||||
// protocol: HTTP2
|
||||
// hosts:
|
||||
// - "*"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// Another example
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: Gateway
|
||||
// metadata:
|
||||
// name: my-tcp-ingress
|
||||
// spec:
|
||||
// selector:
|
||||
// app: my-tcp-ingressgateway
|
||||
// servers:
|
||||
// - port:
|
||||
// number: 27018
|
||||
// name: mongo
|
||||
// protocol: MONGO
|
||||
// hosts:
|
||||
// - "*"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: Gateway
|
||||
// metadata:
|
||||
// name: my-tcp-ingress
|
||||
// spec:
|
||||
// selector:
|
||||
// app: my-tcp-ingressgateway
|
||||
// servers:
|
||||
// - port:
|
||||
// number: 27018
|
||||
// name: mongo
|
||||
// protocol: MONGO
|
||||
// hosts:
|
||||
// - "*"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// The following is an example of TLS configuration for port 443
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: Gateway
|
||||
// metadata:
|
||||
// name: my-tls-ingress
|
||||
// spec:
|
||||
// selector:
|
||||
// app: my-tls-ingressgateway
|
||||
// servers:
|
||||
// - port:
|
||||
// number: 443
|
||||
// name: https
|
||||
// protocol: HTTPS
|
||||
// hosts:
|
||||
// - "*"
|
||||
// tls:
|
||||
// mode: SIMPLE
|
||||
// serverCertificate: /etc/certs/server.pem
|
||||
// privateKey: /etc/certs/privatekey.pem
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: Gateway
|
||||
// metadata:
|
||||
// name: my-tls-ingress
|
||||
// spec:
|
||||
// selector:
|
||||
// app: my-tls-ingressgateway
|
||||
// servers:
|
||||
// - port:
|
||||
// number: 443
|
||||
// name: https
|
||||
// protocol: HTTPS
|
||||
// hosts:
|
||||
// - "*"
|
||||
// tls:
|
||||
// mode: SIMPLE
|
||||
// serverCertificate: /etc/certs/server.pem
|
||||
// privateKey: /etc/certs/privatekey.pem
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
message Server {
|
||||
// The Port on which the proxy should listen for incoming
|
||||
// connections.
|
||||
Port port = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// $hide_from_docs
|
||||
// The ip or the Unix domain socket to which the listener should be bound
|
||||
// to. Format: `x.x.x.x` or `unix:///path/to/uds` or `unix://@foobar`
|
||||
// (Linux abstract namespace). When using Unix domain sockets, the port
|
||||
// number should be 0.
|
||||
string bind = 4;
|
||||
|
||||
// One or more hosts exposed by this gateway.
|
||||
// While typically applicable to
|
||||
// HTTP services, it can also be used for TCP services using TLS with SNI.
|
||||
// A host is specified as a `dnsName` with an optional `namespace/` prefix.
|
||||
// The `dnsName` should be specified using FQDN format, optionally including
|
||||
// a wildcard character in the left-most component (e.g., `prod/*.example.com`).
|
||||
// Set the `dnsName` to `*` to select all `VirtualService` hosts from the
|
||||
// specified namespace (e.g.,`prod/*`).
|
||||
//
|
||||
// The `namespace` can be set to `*` or `.`, representing any or the current
|
||||
// namespace, respectively. For example, `*/foo.example.com` selects the
|
||||
// service from any available namespace while `./foo.example.com` only selects
|
||||
// the service from the namespace of the sidecar. The default, if no `namespace/`
|
||||
// is specified, is `*/`, that is, select services from any namespace.
|
||||
// Any associated `DestinationRule` in the selected namespace will also be used.
|
||||
//
|
||||
// A `VirtualService` must be bound to the gateway and must have one or
|
||||
// more hosts that match the hosts specified in a server. The match
|
||||
// could be an exact match or a suffix match with the server's hosts. For
|
||||
// example, if the server's hosts specifies `*.example.com`, a
|
||||
// `VirtualService` with hosts `dev.example.com` or `prod.example.com` will
|
||||
// match. However, a `VirtualService` with host `example.com` or
|
||||
// `newexample.com` will not match.
|
||||
//
|
||||
// NOTE: Only virtual services exported to the gateway's namespace
|
||||
// (e.g., `exportTo` value of `*`) can be referenced.
|
||||
// Private configurations (e.g., `exportTo` set to `.`) will not be
|
||||
// available. Refer to the `exportTo` setting in `VirtualService`,
|
||||
// `DestinationRule`, and `ServiceEntry` configurations for details.
|
||||
repeated string hosts = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Set of TLS related options that govern the server's behavior. Use
|
||||
// these options to control if all http requests should be redirected to
|
||||
// https, and the TLS modes to use.
|
||||
ServerTLSSettings tls = 3;
|
||||
|
||||
// The loopback IP endpoint or Unix domain socket to which traffic should
|
||||
// be forwarded to by default. Format should be `127.0.0.1:PORT` or
|
||||
// `unix:///path/to/socket` or `unix://@foobar` (Linux abstract namespace).
|
||||
// NOT IMPLEMENTED.
|
||||
// $hide_from_docs
|
||||
string default_endpoint = 5;
|
||||
|
||||
// An optional name of the server, when set must be unique across all servers.
|
||||
// This will be used for variety of purposes like prefixing stats generated with
|
||||
// this name etc.
|
||||
string name = 6;
|
||||
}
|
||||
|
||||
// Port describes the properties of a specific port of a service.
|
||||
message Port {
|
||||
// A valid non-negative integer port number.
|
||||
uint32 number = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// The protocol exposed on the port.
|
||||
// MUST BE one of HTTP|HTTPS|GRPC|HTTP2|MONGO|TCP|TLS.
|
||||
// TLS implies the connection will be routed based on the SNI header to
|
||||
// the destination without terminating the TLS connection.
|
||||
string protocol = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Label assigned to the port.
|
||||
string name = 3 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// The port number on the endpoint where the traffic will be
|
||||
// received. Applicable only when used with ServiceEntries.
|
||||
uint32 target_port = 4;
|
||||
}
|
||||
|
||||
message ServerTLSSettings {
|
||||
// If set to true, the load balancer will send a 301 redirect for
|
||||
// all http connections, asking the clients to use HTTPS.
|
||||
bool https_redirect = 1;
|
||||
|
||||
// TLS modes enforced by the proxy
|
||||
enum TLSmode {
|
||||
// The SNI string presented by the client will be used as the
|
||||
// match criterion in a VirtualService TLS route to determine
|
||||
// the destination service from the service registry.
|
||||
PASSTHROUGH = 0;
|
||||
|
||||
// Secure connections with standard TLS semantics.
|
||||
SIMPLE = 1;
|
||||
|
||||
// Secure connections to the downstream using mutual TLS by
|
||||
// presenting server certificates for authentication.
|
||||
MUTUAL = 2;
|
||||
|
||||
// Similar to the passthrough mode, except servers with this TLS
|
||||
// mode do not require an associated VirtualService to map from
|
||||
// the SNI value to service in the registry. The destination
|
||||
// details such as the service/subset/port are encoded in the
|
||||
// SNI value. The proxy will forward to the upstream (Envoy)
|
||||
// cluster (a group of endpoints) specified by the SNI
|
||||
// value. This server is typically used to provide connectivity
|
||||
// between services in disparate L3 networks that otherwise do
|
||||
// not have direct connectivity between their respective
|
||||
// endpoints. Use of this mode assumes that both the source and
|
||||
// the destination are using Istio mTLS to secure traffic.
|
||||
AUTO_PASSTHROUGH = 3;
|
||||
|
||||
// Secure connections from the downstream using mutual TLS by
|
||||
// presenting server certificates for authentication. Compared
|
||||
// to Mutual mode, this mode uses certificates, representing
|
||||
// gateway workload identity, generated automatically by Istio
|
||||
// for mTLS authentication. When this mode is used, all other
|
||||
// fields in `TLSOptions` should be empty.
|
||||
ISTIO_MUTUAL = 4;
|
||||
};
|
||||
|
||||
// Optional: Indicates whether connections to this port should be
|
||||
// secured using TLS. The value of this field determines how TLS is
|
||||
// enforced.
|
||||
TLSmode mode = 2;
|
||||
|
||||
// REQUIRED if mode is `SIMPLE` or `MUTUAL`. The path to the file
|
||||
// holding the server-side TLS certificate to use.
|
||||
string server_certificate = 3;
|
||||
|
||||
// REQUIRED if mode is `SIMPLE` or `MUTUAL`. The path to the file
|
||||
// holding the server's private key.
|
||||
string private_key = 4;
|
||||
|
||||
// REQUIRED if mode is `MUTUAL`. The path to a file containing
|
||||
// certificate authority certificates to use in verifying a presented
|
||||
// client side certificate.
|
||||
string ca_certificates = 5;
|
||||
|
||||
// For gateways running on Kubernetes, the name of the secret that
|
||||
// holds the TLS certs including the CA certificates. Applicable
|
||||
// only on Kubernetes. The secret (of type `generic`) should
|
||||
// contain the following keys and values: `key:
|
||||
// <privateKey>` and `cert: <serverCert>`. For mutual TLS,
|
||||
// `cacert: <CACertificate>` can be provided in the same secret or
|
||||
// a separate secret named `<secret>-cacert`.
|
||||
// Secret of type tls for server certificates along with
|
||||
// ca.crt key for CA certificates is also supported.
|
||||
// Only one of server certificates and CA certificate
|
||||
// or credentialName can be specified.
|
||||
string credential_name = 10;
|
||||
|
||||
// A list of alternate names to verify the subject identity in the
|
||||
// certificate presented by the client.
|
||||
repeated string subject_alt_names = 6;
|
||||
|
||||
// An optional list of base64-encoded SHA-256 hashes of the SKPIs of
|
||||
// authorized client certificates.
|
||||
// Note: When both verify_certificate_hash and verify_certificate_spki
|
||||
// are specified, a hash matching either value will result in the
|
||||
// certificate being accepted.
|
||||
repeated string verify_certificate_spki = 11;
|
||||
|
||||
// An optional list of hex-encoded SHA-256 hashes of the
|
||||
// authorized client certificates. Both simple and colon separated
|
||||
// formats are acceptable.
|
||||
// Note: When both verify_certificate_hash and verify_certificate_spki
|
||||
// are specified, a hash matching either value will result in the
|
||||
// certificate being accepted.
|
||||
repeated string verify_certificate_hash = 12;
|
||||
|
||||
// TLS protocol versions.
|
||||
enum TLSProtocol {
|
||||
// Automatically choose the optimal TLS version.
|
||||
TLS_AUTO = 0;
|
||||
|
||||
// TLS version 1.0
|
||||
TLSV1_0 = 1;
|
||||
|
||||
// TLS version 1.1
|
||||
TLSV1_1 = 2;
|
||||
|
||||
// TLS version 1.2
|
||||
TLSV1_2 = 3;
|
||||
|
||||
// TLS version 1.3
|
||||
TLSV1_3 = 4;
|
||||
}
|
||||
|
||||
// Optional: Minimum TLS protocol version.
|
||||
TLSProtocol min_protocol_version = 7;
|
||||
|
||||
// Optional: Maximum TLS protocol version.
|
||||
TLSProtocol max_protocol_version = 8;
|
||||
|
||||
// Optional: If specified, only support the specified cipher list.
|
||||
// Otherwise default to the default cipher list supported by Envoy.
|
||||
repeated string cipher_suites = 9;
|
||||
}
|
||||
@ -0,0 +1,957 @@
|
||||
// Copyright 2018 Istio Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
import "google/api/field_behavior.proto";
|
||||
import "networking/v1alpha3/gateway.proto";
|
||||
import "networking/v1alpha3/sidecar.proto";
|
||||
import "networking/v1alpha3/workload_entry.proto";
|
||||
|
||||
// $schema: istio.networking.v1alpha3.ServiceEntry
|
||||
// $title: Service Entry
|
||||
// $description: Configuration affecting service registry.
|
||||
// $location: https://istio.io/docs/reference/config/networking/service-entry.html
|
||||
// $aliases: [/docs/reference/config/networking/v1alpha3/service-entry]
|
||||
|
||||
// `ServiceEntry` enables adding additional entries into Istio's
|
||||
// internal service registry, so that auto-discovered services in the
|
||||
// mesh can access/route to these manually specified services. A
|
||||
// service entry describes the properties of a service (DNS name,
|
||||
// VIPs, ports, protocols, endpoints). These services could be
|
||||
// external to the mesh (e.g., web APIs) or mesh-internal services
|
||||
// that are not part of the platform's service registry (e.g., a set
|
||||
// of VMs talking to services in Kubernetes). In addition, the
|
||||
// endpoints of a service entry can also be dynamically selected by
|
||||
// using the `workloadSelector` field. These endpoints can be VM
|
||||
// workloads declared using the `WorkloadEntry` object or Kubernetes
|
||||
// pods. The ability to select both pods and VMs under a single
|
||||
// service allows for migration of services from VMs to Kubernetes
|
||||
// without having to change the existing DNS names associated with the
|
||||
// services.
|
||||
//
|
||||
// The following example declares a few external APIs accessed by internal
|
||||
// applications over HTTPS. The sidecar inspects the SNI value in the
|
||||
// ClientHello message to route to the appropriate external service.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: external-svc-https
|
||||
// spec:
|
||||
// hosts:
|
||||
// - api.dropboxapi.com
|
||||
// - www.googleapis.com
|
||||
// - api.facebook.com
|
||||
// location: MESH_EXTERNAL
|
||||
// ports:
|
||||
// - number: 443
|
||||
// name: https
|
||||
// protocol: TLS
|
||||
// resolution: DNS
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: external-svc-https
|
||||
// spec:
|
||||
// hosts:
|
||||
// - api.dropboxapi.com
|
||||
// - www.googleapis.com
|
||||
// - api.facebook.com
|
||||
// location: MESH_EXTERNAL
|
||||
// ports:
|
||||
// - number: 443
|
||||
// name: https
|
||||
// protocol: TLS
|
||||
// resolution: DNS
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// The following configuration adds a set of MongoDB instances running on
|
||||
// unmanaged VMs to Istio's registry, so that these services can be treated
|
||||
// as any other service in the mesh. The associated DestinationRule is used
|
||||
// to initiate mTLS connections to the database instances.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: external-svc-mongocluster
|
||||
// spec:
|
||||
// hosts:
|
||||
// - mymongodb.somedomain # not used
|
||||
// addresses:
|
||||
// - 192.192.192.192/24 # VIPs
|
||||
// ports:
|
||||
// - number: 27018
|
||||
// name: mongodb
|
||||
// protocol: MONGO
|
||||
// location: MESH_INTERNAL
|
||||
// resolution: STATIC
|
||||
// endpoints:
|
||||
// - address: 2.2.2.2
|
||||
// - address: 3.3.3.3
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: external-svc-mongocluster
|
||||
// spec:
|
||||
// hosts:
|
||||
// - mymongodb.somedomain # not used
|
||||
// addresses:
|
||||
// - 192.192.192.192/24 # VIPs
|
||||
// ports:
|
||||
// - number: 27018
|
||||
// name: mongodb
|
||||
// protocol: MONGO
|
||||
// location: MESH_INTERNAL
|
||||
// resolution: STATIC
|
||||
// endpoints:
|
||||
// - address: 2.2.2.2
|
||||
// - address: 3.3.3.3
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// and the associated DestinationRule
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: DestinationRule
|
||||
// metadata:
|
||||
// name: mtls-mongocluster
|
||||
// spec:
|
||||
// host: mymongodb.somedomain
|
||||
// trafficPolicy:
|
||||
// tls:
|
||||
// mode: MUTUAL
|
||||
// clientCertificate: /etc/certs/myclientcert.pem
|
||||
// privateKey: /etc/certs/client_private_key.pem
|
||||
// caCertificates: /etc/certs/rootcacerts.pem
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: DestinationRule
|
||||
// metadata:
|
||||
// name: mtls-mongocluster
|
||||
// spec:
|
||||
// host: mymongodb.somedomain
|
||||
// trafficPolicy:
|
||||
// tls:
|
||||
// mode: MUTUAL
|
||||
// clientCertificate: /etc/certs/myclientcert.pem
|
||||
// privateKey: /etc/certs/client_private_key.pem
|
||||
// caCertificates: /etc/certs/rootcacerts.pem
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// The following example uses a combination of service entry and TLS
|
||||
// routing in a virtual service to steer traffic based on the SNI value to
|
||||
// an internal egress firewall.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: external-svc-redirect
|
||||
// spec:
|
||||
// hosts:
|
||||
// - wikipedia.org
|
||||
// - "*.wikipedia.org"
|
||||
// location: MESH_EXTERNAL
|
||||
// ports:
|
||||
// - number: 443
|
||||
// name: https
|
||||
// protocol: TLS
|
||||
// resolution: NONE
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: external-svc-redirect
|
||||
// spec:
|
||||
// hosts:
|
||||
// - wikipedia.org
|
||||
// - "*.wikipedia.org"
|
||||
// location: MESH_EXTERNAL
|
||||
// ports:
|
||||
// - number: 443
|
||||
// name: https
|
||||
// protocol: TLS
|
||||
// resolution: NONE
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// And the associated VirtualService to route based on the SNI value.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: VirtualService
|
||||
// metadata:
|
||||
// name: tls-routing
|
||||
// spec:
|
||||
// hosts:
|
||||
// - wikipedia.org
|
||||
// - "*.wikipedia.org"
|
||||
// tls:
|
||||
// - match:
|
||||
// - sniHosts:
|
||||
// - wikipedia.org
|
||||
// - "*.wikipedia.org"
|
||||
// route:
|
||||
// - destination:
|
||||
// host: internal-egress-firewall.ns1.svc.cluster.local
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: VirtualService
|
||||
// metadata:
|
||||
// name: tls-routing
|
||||
// spec:
|
||||
// hosts:
|
||||
// - wikipedia.org
|
||||
// - "*.wikipedia.org"
|
||||
// tls:
|
||||
// - match:
|
||||
// - sniHosts:
|
||||
// - wikipedia.org
|
||||
// - "*.wikipedia.org"
|
||||
// route:
|
||||
// - destination:
|
||||
// host: internal-egress-firewall.ns1.svc.cluster.local
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// The virtual service with TLS match serves to override the default SNI
|
||||
// match. In the absence of a virtual service, traffic will be forwarded to
|
||||
// the wikipedia domains.
|
||||
//
|
||||
// The following example demonstrates the use of a dedicated egress gateway
|
||||
// through which all external service traffic is forwarded.
|
||||
// The 'exportTo' field allows for control over the visibility of a service
|
||||
// declaration to other namespaces in the mesh. By default, a service is exported
|
||||
// to all namespaces. The following example restricts the visibility to the
|
||||
// current namespace, represented by ".", so that it cannot be used by other
|
||||
// namespaces.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: external-svc-httpbin
|
||||
// namespace : egress
|
||||
// spec:
|
||||
// hosts:
|
||||
// - httpbin.com
|
||||
// exportTo:
|
||||
// - "."
|
||||
// location: MESH_EXTERNAL
|
||||
// ports:
|
||||
// - number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// resolution: DNS
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: external-svc-httpbin
|
||||
// namespace : egress
|
||||
// spec:
|
||||
// hosts:
|
||||
// - httpbin.com
|
||||
// exportTo:
|
||||
// - "."
|
||||
// location: MESH_EXTERNAL
|
||||
// ports:
|
||||
// - number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// resolution: DNS
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// Define a gateway to handle all egress traffic.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: Gateway
|
||||
// metadata:
|
||||
// name: istio-egressgateway
|
||||
// namespace: istio-system
|
||||
// spec:
|
||||
// selector:
|
||||
// istio: egressgateway
|
||||
// servers:
|
||||
// - port:
|
||||
// number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// hosts:
|
||||
// - "*"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: Gateway
|
||||
// metadata:
|
||||
// name: istio-egressgateway
|
||||
// namespace: istio-system
|
||||
// spec:
|
||||
// selector:
|
||||
// istio: egressgateway
|
||||
// servers:
|
||||
// - port:
|
||||
// number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// hosts:
|
||||
// - "*"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// And the associated `VirtualService` to route from the sidecar to the
|
||||
// gateway service (`istio-egressgateway.istio-system.svc.cluster.local`), as
|
||||
// well as route from the gateway to the external service. Note that the
|
||||
// virtual service is exported to all namespaces enabling them to route traffic
|
||||
// through the gateway to the external service. Forcing traffic to go through
|
||||
// a managed middle proxy like this is a common practice.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: VirtualService
|
||||
// metadata:
|
||||
// name: gateway-routing
|
||||
// namespace: egress
|
||||
// spec:
|
||||
// hosts:
|
||||
// - httpbin.com
|
||||
// exportTo:
|
||||
// - "*"
|
||||
// gateways:
|
||||
// - mesh
|
||||
// - istio-egressgateway
|
||||
// http:
|
||||
// - match:
|
||||
// - port: 80
|
||||
// gateways:
|
||||
// - mesh
|
||||
// route:
|
||||
// - destination:
|
||||
// host: istio-egressgateway.istio-system.svc.cluster.local
|
||||
// - match:
|
||||
// - port: 80
|
||||
// gateways:
|
||||
// - istio-egressgateway
|
||||
// route:
|
||||
// - destination:
|
||||
// host: httpbin.com
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: VirtualService
|
||||
// metadata:
|
||||
// name: gateway-routing
|
||||
// namespace: egress
|
||||
// spec:
|
||||
// hosts:
|
||||
// - httpbin.com
|
||||
// exportTo:
|
||||
// - "*"
|
||||
// gateways:
|
||||
// - mesh
|
||||
// - istio-egressgateway
|
||||
// http:
|
||||
// - match:
|
||||
// - port: 80
|
||||
// gateways:
|
||||
// - mesh
|
||||
// route:
|
||||
// - destination:
|
||||
// host: istio-egressgateway.istio-system.svc.cluster.local
|
||||
// - match:
|
||||
// - port: 80
|
||||
// gateways:
|
||||
// - istio-egressgateway
|
||||
// route:
|
||||
// - destination:
|
||||
// host: httpbin.com
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// The following example demonstrates the use of wildcards in the hosts for
|
||||
// external services. If the connection has to be routed to the IP address
|
||||
// requested by the application (i.e. application resolves DNS and attempts
|
||||
// to connect to a specific IP), the discovery mode must be set to `NONE`.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: external-svc-wildcard-example
|
||||
// spec:
|
||||
// hosts:
|
||||
// - "*.bar.com"
|
||||
// location: MESH_EXTERNAL
|
||||
// ports:
|
||||
// - number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// resolution: NONE
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: external-svc-wildcard-example
|
||||
// spec:
|
||||
// hosts:
|
||||
// - "*.bar.com"
|
||||
// location: MESH_EXTERNAL
|
||||
// ports:
|
||||
// - number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// resolution: NONE
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// The following example demonstrates a service that is available via a
|
||||
// Unix Domain Socket on the host of the client. The resolution must be
|
||||
// set to STATIC to use Unix address endpoints.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: unix-domain-socket-example
|
||||
// spec:
|
||||
// hosts:
|
||||
// - "example.unix.local"
|
||||
// location: MESH_EXTERNAL
|
||||
// ports:
|
||||
// - number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// resolution: STATIC
|
||||
// endpoints:
|
||||
// - address: unix:///var/run/example/socket
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: unix-domain-socket-example
|
||||
// spec:
|
||||
// hosts:
|
||||
// - "example.unix.local"
|
||||
// location: MESH_EXTERNAL
|
||||
// ports:
|
||||
// - number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// resolution: STATIC
|
||||
// endpoints:
|
||||
// - address: unix:///var/run/example/socket
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// For HTTP-based services, it is possible to create a `VirtualService`
|
||||
// backed by multiple DNS addressable endpoints. In such a scenario, the
|
||||
// application can use the `HTTP_PROXY` environment variable to transparently
|
||||
// reroute API calls for the `VirtualService` to a chosen backend. For
|
||||
// example, the following configuration creates a non-existent external
|
||||
// service called foo.bar.com backed by three domains: us.foo.bar.com:8080,
|
||||
// uk.foo.bar.com:9080, and in.foo.bar.com:7080
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: external-svc-dns
|
||||
// spec:
|
||||
// hosts:
|
||||
// - foo.bar.com
|
||||
// location: MESH_EXTERNAL
|
||||
// ports:
|
||||
// - number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// resolution: DNS
|
||||
// endpoints:
|
||||
// - address: us.foo.bar.com
|
||||
// ports:
|
||||
// http: 8080
|
||||
// - address: uk.foo.bar.com
|
||||
// ports:
|
||||
// http: 9080
|
||||
// - address: in.foo.bar.com
|
||||
// ports:
|
||||
// http: 7080
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: external-svc-dns
|
||||
// spec:
|
||||
// hosts:
|
||||
// - foo.bar.com
|
||||
// location: MESH_EXTERNAL
|
||||
// ports:
|
||||
// - number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// resolution: DNS
|
||||
// endpoints:
|
||||
// - address: us.foo.bar.com
|
||||
// ports:
|
||||
// https: 8080
|
||||
// - address: uk.foo.bar.com
|
||||
// ports:
|
||||
// https: 9080
|
||||
// - address: in.foo.bar.com
|
||||
// ports:
|
||||
// https: 7080
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// With `HTTP_PROXY=http://localhost/`, calls from the application to
|
||||
// `http://foo.bar.com` will be load balanced across the three domains
|
||||
// specified above. In other words, a call to `http://foo.bar.com/baz` would
|
||||
// be translated to `http://uk.foo.bar.com/baz`.
|
||||
//
|
||||
// The following example illustrates the usage of a `ServiceEntry`
|
||||
// containing a subject alternate name
|
||||
// whose format conforms to the [SPIFFE standard](https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md):
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: httpbin
|
||||
// namespace : httpbin-ns
|
||||
// spec:
|
||||
// hosts:
|
||||
// - httpbin.com
|
||||
// location: MESH_INTERNAL
|
||||
// ports:
|
||||
// - number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// resolution: STATIC
|
||||
// endpoints:
|
||||
// - address: 2.2.2.2
|
||||
// - address: 3.3.3.3
|
||||
// subjectAltNames:
|
||||
// - "spiffe://cluster.local/ns/httpbin-ns/sa/httpbin-service-account"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: httpbin
|
||||
// namespace : httpbin-ns
|
||||
// spec:
|
||||
// hosts:
|
||||
// - httpbin.com
|
||||
// location: MESH_INTERNAL
|
||||
// ports:
|
||||
// - number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// resolution: STATIC
|
||||
// endpoints:
|
||||
// - address: 2.2.2.2
|
||||
// - address: 3.3.3.3
|
||||
// subjectAltNames:
|
||||
// - "spiffe://cluster.local/ns/httpbin-ns/sa/httpbin-service-account"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// The following example demonstrates the use of `ServiceEntry` with a
|
||||
// `workloadSelector` to handle the migration of a service
|
||||
// `details.bookinfo.com` from VMs to Kubernetes. The service has two
|
||||
// VM-based instances with sidecars as well as a set of Kubernetes
|
||||
// pods managed by a standard deployment object. Consumers of this
|
||||
// service in the mesh will be automatically load balanced across the
|
||||
// VMs and Kubernetes. VM for the `details.bookinfo.com`
|
||||
// service. This VM has sidecar installed and bootstrapped using the
|
||||
// `details-legacy` service account. The sidecar receives HTTP traffic
|
||||
// on port 80 (wrapped in istio mutual TLS) and forwards it to the
|
||||
// application on the localhost on the same port.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: WorkloadEntry
|
||||
// metadata:
|
||||
// name: details-vm-1
|
||||
// spec:
|
||||
// serviceAccount: details
|
||||
// address: 2.2.2.2
|
||||
// labels:
|
||||
// app: details
|
||||
// instance-id: vm1
|
||||
// ---
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: WorkloadEntry
|
||||
// metadata:
|
||||
// name: details-vm-2
|
||||
// spec:
|
||||
// serviceAccount: details
|
||||
// address: 3.3.3.3
|
||||
// labels:
|
||||
// app: details
|
||||
// instance-id: vm2
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: WorkloadEntry
|
||||
// metadata:
|
||||
// name: details-vm-1
|
||||
// spec:
|
||||
// serviceAccount: details
|
||||
// address: 2.2.2.2
|
||||
// labels:
|
||||
// app: details
|
||||
// instance-id: vm1
|
||||
// ---
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: WorkloadEntry
|
||||
// metadata:
|
||||
// name: details-vm-2
|
||||
// spec:
|
||||
// serviceAccount: details
|
||||
// address: 3.3.3.3
|
||||
// labels:
|
||||
// app: details
|
||||
// instance-id: vm2
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// Assuming there is also a Kubernetes deployment with pod labels
|
||||
// `app: details` using the same service account `details`, the
|
||||
// following service entry declares a service spanning both VMs and
|
||||
// Kubernetes:
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: details-svc
|
||||
// spec:
|
||||
// hosts:
|
||||
// - details.bookinfo.com
|
||||
// location: MESH_INTERNAL
|
||||
// ports:
|
||||
// - number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// resolution: STATIC
|
||||
// workloadSelector:
|
||||
// labels:
|
||||
// app: details
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: details-svc
|
||||
// spec:
|
||||
// hosts:
|
||||
// - details.bookinfo.com
|
||||
// location: MESH_INTERNAL
|
||||
// ports:
|
||||
// - number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// resolution: STATIC
|
||||
// workloadSelector:
|
||||
// labels:
|
||||
// app: details
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
package istio.networking.v1alpha3;
|
||||
|
||||
option go_package = "istio.io/api/networking/v1alpha3";
|
||||
|
||||
// ServiceEntry enables adding additional entries into Istio's internal
|
||||
// service registry.
|
||||
//
|
||||
// <!-- crd generation tags
|
||||
// +cue-gen:ServiceEntry:groupName:networking.istio.io
|
||||
// +cue-gen:ServiceEntry:version:v1alpha3
|
||||
// +cue-gen:ServiceEntry:storageVersion
|
||||
// +cue-gen:ServiceEntry:annotations:helm.sh/resource-policy=keep
|
||||
// +cue-gen:ServiceEntry:labels:app=istio-pilot,chart=istio,heritage=Tiller,release=istio
|
||||
// +cue-gen:ServiceEntry:subresource:status
|
||||
// +cue-gen:ServiceEntry:scope:Namespaced
|
||||
// +cue-gen:ServiceEntry:resource:categories=istio-io,networking-istio-io,shortNames=se,plural=serviceentries
|
||||
// +cue-gen:ServiceEntry:printerColumn:name=Hosts,type=string,JSONPath=.spec.hosts,description="The hosts associated with the ServiceEntry"
|
||||
// +cue-gen:ServiceEntry:printerColumn:name=Location,type=string,JSONPath=.spec.location,description="Whether the service is external to the
|
||||
// mesh or part of the mesh (MESH_EXTERNAL or MESH_INTERNAL)"
|
||||
// +cue-gen:ServiceEntry:printerColumn:name=Resolution,type=string,JSONPath=.spec.resolution,description="Service discovery mode for the hosts
|
||||
// (NONE, STATIC, or DNS)"
|
||||
// +cue-gen:ServiceEntry:printerColumn:name=Age,type=date,JSONPath=.metadata.creationTimestamp,description="CreationTimestamp is a timestamp
|
||||
// representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations.
|
||||
// Clients may not set this value. It is represented in RFC3339 form and is in UTC.
|
||||
// Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"
|
||||
// +cue-gen:ServiceEntry:preserveUnknownFields:false
|
||||
// -->
|
||||
//
|
||||
// <!-- go code generation tags
|
||||
// +kubetype-gen
|
||||
// +kubetype-gen:groupVersion=networking.istio.io/v1alpha3
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen=true
|
||||
// -->
|
||||
message ServiceEntry {
|
||||
// The hosts associated with the ServiceEntry. Could be a DNS
|
||||
// name with wildcard prefix.
|
||||
//
|
||||
// 1. The hosts field is used to select matching hosts in VirtualServices and DestinationRules.
|
||||
// 2. For HTTP traffic the HTTP Host/Authority header will be matched against the hosts field.
|
||||
// 3. For HTTPs or TLS traffic containing Server Name Indication (SNI), the SNI value
|
||||
// will be matched against the hosts field.
|
||||
//
|
||||
// **NOTE 1:** When resolution is set to type DNS and no endpoints
|
||||
// are specified, the host field will be used as the DNS name of the
|
||||
// endpoint to route traffic to.
|
||||
//
|
||||
// **NOTE 2:** If the hostname matches with the name of a service
|
||||
// from another service registry such as Kubernetes that also
|
||||
// supplies its own set of endpoints, the ServiceEntry will be
|
||||
// treated as a decorator of the existing Kubernetes
|
||||
// service. Properties in the service entry will be added to the
|
||||
// Kubernetes service if applicable. Currently, the only the
|
||||
// following additional properties will be considered by `istiod`:
|
||||
//
|
||||
// 1. subjectAltNames: In addition to verifying the SANs of the
|
||||
// service accounts associated with the pods of the service, the
|
||||
// SANs specified here will also be verified.
|
||||
//
|
||||
repeated string hosts = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// The virtual IP addresses associated with the service. Could be CIDR
|
||||
// prefix. For HTTP traffic, generated route configurations will include http route
|
||||
// domains for both the `addresses` and `hosts` field values and the destination will
|
||||
// be identified based on the HTTP Host/Authority header.
|
||||
// If one or more IP addresses are specified,
|
||||
// the incoming traffic will be identified as belonging to this service
|
||||
// if the destination IP matches the IP/CIDRs specified in the addresses
|
||||
// field. If the Addresses field is empty, traffic will be identified
|
||||
// solely based on the destination port. In such scenarios, the port on
|
||||
// which the service is being accessed must not be shared by any other
|
||||
// service in the mesh. In other words, the sidecar will behave as a
|
||||
// simple TCP proxy, forwarding incoming traffic on a specified port to
|
||||
// the specified destination endpoint IP/host. Unix domain socket
|
||||
// addresses are not supported in this field.
|
||||
repeated string addresses = 2;
|
||||
|
||||
// The ports associated with the external service. If the
|
||||
// Endpoints are Unix domain socket addresses, there must be exactly one
|
||||
// port.
|
||||
repeated Port ports = 3 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Location specifies whether the service is part of Istio mesh or
|
||||
// outside the mesh. Location determines the behavior of several
|
||||
// features, such as service-to-service mTLS authentication, policy
|
||||
// enforcement, etc. When communicating with services outside the mesh,
|
||||
// Istio's mTLS authentication is disabled, and policy enforcement is
|
||||
// performed on the client-side as opposed to server-side.
|
||||
enum Location {
|
||||
// Signifies that the service is external to the mesh. Typically used
|
||||
// to indicate external services consumed through APIs.
|
||||
MESH_EXTERNAL = 0;
|
||||
|
||||
// Signifies that the service is part of the mesh. Typically used to
|
||||
// indicate services added explicitly as part of expanding the service
|
||||
// mesh to include unmanaged infrastructure (e.g., VMs added to a
|
||||
// Kubernetes based service mesh).
|
||||
MESH_INTERNAL = 1;
|
||||
};
|
||||
|
||||
// Specify whether the service should be considered external to the mesh
|
||||
// or part of the mesh.
|
||||
Location location = 4;
|
||||
|
||||
// Resolution determines how the proxy will resolve the IP addresses of
|
||||
// the network endpoints associated with the service, so that it can
|
||||
// route to one of them. The resolution mode specified here has no impact
|
||||
// on how the application resolves the IP address associated with the
|
||||
// service. The application may still have to use DNS to resolve the
|
||||
// service to an IP so that the outbound traffic can be captured by the
|
||||
// Proxy. Alternatively, for HTTP services, the application could
|
||||
// directly communicate with the proxy (e.g., by setting HTTP_PROXY) to
|
||||
// talk to these services.
|
||||
enum Resolution {
|
||||
// Assume that incoming connections have already been resolved (to a
|
||||
// specific destination IP address). Such connections are typically
|
||||
// routed via the proxy using mechanisms such as IP table REDIRECT/
|
||||
// eBPF. After performing any routing related transformations, the
|
||||
// proxy will forward the connection to the IP address to which the
|
||||
// connection was bound.
|
||||
NONE = 0;
|
||||
|
||||
// Use the static IP addresses specified in endpoints (see below) as the
|
||||
// backing instances associated with the service.
|
||||
STATIC = 1;
|
||||
|
||||
// Attempt to resolve the IP address by querying the ambient DNS,
|
||||
// during request processing. If no endpoints are specified, the proxy
|
||||
// will resolve the DNS address specified in the hosts field, if
|
||||
// wildcards are not used. If endpoints are specified, the DNS
|
||||
// addresses specified in the endpoints will be resolved to determine
|
||||
// the destination IP address. DNS resolution cannot be used with Unix
|
||||
// domain socket endpoints.
|
||||
DNS = 2;
|
||||
};
|
||||
|
||||
// Service discovery mode for the hosts. Care must be taken
|
||||
// when setting the resolution mode to NONE for a TCP port without
|
||||
// accompanying IP addresses. In such cases, traffic to any IP on
|
||||
// said port will be allowed (i.e. `0.0.0.0:<port>`).
|
||||
Resolution resolution = 5 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// One or more endpoints associated with the service. Only one of
|
||||
// `endpoints` or `workloadSelector` can be specified.
|
||||
repeated WorkloadEntry endpoints = 6;
|
||||
|
||||
// Applicable only for MESH_INTERNAL services. Only one of
|
||||
// `endpoints` or `workloadSelector` can be specified. Selects one
|
||||
// or more Kubernetes pods or VM workloads (specified using
|
||||
// `WorkloadEntry`) based on their labels. The `WorkloadEntry` object
|
||||
// representing the VMs should be defined in the same namespace as
|
||||
// the ServiceEntry.
|
||||
WorkloadSelector workload_selector = 9;
|
||||
|
||||
// A list of namespaces to which this service is exported. Exporting a service
|
||||
// allows it to be used by sidecars, gateways and virtual services defined in
|
||||
// other namespaces. This feature provides a mechanism for service owners
|
||||
// and mesh administrators to control the visibility of services across
|
||||
// namespace boundaries.
|
||||
//
|
||||
// If no namespaces are specified then the service is exported to all
|
||||
// namespaces by default.
|
||||
//
|
||||
// The value "." is reserved and defines an export to the same namespace that
|
||||
// the service is declared in. Similarly the value "*" is reserved and
|
||||
// defines an export to all namespaces.
|
||||
//
|
||||
// For a Kubernetes Service, the equivalent effect can be achieved by setting
|
||||
// the annotation "networking.istio.io/exportTo" to a comma-separated list
|
||||
// of namespace names.
|
||||
//
|
||||
// NOTE: in the current release, the `exportTo` value is restricted to
|
||||
// "." or "*" (i.e., the current namespace or all namespaces).
|
||||
repeated string export_to = 7;
|
||||
|
||||
// If specified, the proxy will verify that the server certificate's
|
||||
// subject alternate name matches one of the specified values.
|
||||
//
|
||||
// NOTE: When using the workloadEntry with workloadSelectors, the
|
||||
// service account specified in the workloadEntry will also be used
|
||||
// to derive the additional subject alternate names that should be
|
||||
// verified.
|
||||
repeated string subject_alt_names = 8;
|
||||
}
|
||||
639
istio/src/main/resources/proto/networking/v1alpha3/sidecar.proto
Normal file
639
istio/src/main/resources/proto/networking/v1alpha3/sidecar.proto
Normal file
@ -0,0 +1,639 @@
|
||||
// Copyright 2018 Istio Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
import "google/api/field_behavior.proto";
|
||||
import "networking/v1alpha3/gateway.proto";
|
||||
import "networking/v1alpha3/virtual_service.proto";
|
||||
import "networking/v1alpha3/destination_rule.proto";
|
||||
|
||||
// $schema: istio.networking.v1alpha3.Sidecar
|
||||
// $title: Sidecar
|
||||
// $description: Configuration affecting network reachability of a sidecar.
|
||||
// $location: https://istio.io/docs/reference/config/networking/sidecar.html
|
||||
// $aliases: [/docs/reference/config/networking/v1alpha3/sidecar]
|
||||
|
||||
// `Sidecar` describes the configuration of the sidecar proxy that mediates
|
||||
// inbound and outbound communication to the workload instance it is attached to. By
|
||||
// default, Istio will program all sidecar proxies in the mesh with the
|
||||
// necessary configuration required to reach every workload instance in the mesh, as
|
||||
// well as accept traffic on all the ports associated with the
|
||||
// workload. The `Sidecar` configuration provides a way to fine tune the set of
|
||||
// ports, protocols that the proxy will accept when forwarding traffic to
|
||||
// and from the workload. In addition, it is possible to restrict the set
|
||||
// of services that the proxy can reach when forwarding outbound traffic
|
||||
// from workload instances.
|
||||
//
|
||||
// Services and configuration in a mesh are organized into one or more
|
||||
// namespaces (e.g., a Kubernetes namespace or a CF org/space). A `Sidecar`
|
||||
// configuration in a namespace will apply to one or more workload instances in the same
|
||||
// namespace, selected using the `workloadSelector` field. In the absence of a
|
||||
// `workloadSelector`, it will apply to all workload instances in the same
|
||||
// namespace. When determining the `Sidecar` configuration to be applied to a
|
||||
// workload instance, preference will be given to the resource with a
|
||||
// `workloadSelector` that selects this workload instance, over a `Sidecar` configuration
|
||||
// without any `workloadSelector`.
|
||||
//
|
||||
// **NOTE 1**: *_Each namespace can have only one `Sidecar`
|
||||
// configuration without any `workloadSelector`_ that specifies the
|
||||
// default for all pods in that namespace*. It is recommended to use
|
||||
// the name `default` for the namespace-wide sidecar. The behavior of
|
||||
// the system is undefined if more than one selector-less `Sidecar`
|
||||
// configurations exist in a given namespace. The behavior of the
|
||||
// system is undefined if two or more `Sidecar` configurations with a
|
||||
// `workloadSelector` select the same workload instance.
|
||||
//
|
||||
// **NOTE 2**: *_A `Sidecar` configuration in the `MeshConfig`
|
||||
// [root namespace](https://istio.io/docs/reference/config/istio.mesh.v1alpha1/#MeshConfig)
|
||||
// will be applied by default to all namespaces without a `Sidecar`
|
||||
// configuration_*. This global default `Sidecar` configuration should not have
|
||||
// any `workloadSelector`.
|
||||
//
|
||||
// The example below declares a global default `Sidecar` configuration
|
||||
// in the root namespace called `istio-config`, that configures
|
||||
// sidecars in all namespaces to allow egress traffic only to other
|
||||
// workloads in the same namespace as well as to services in the
|
||||
// `istio-system` namespace.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: Sidecar
|
||||
// metadata:
|
||||
// name: default
|
||||
// namespace: istio-config
|
||||
// spec:
|
||||
// egress:
|
||||
// - hosts:
|
||||
// - "./*"
|
||||
// - "istio-system/*"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: Sidecar
|
||||
// metadata:
|
||||
// name: default
|
||||
// namespace: istio-config
|
||||
// spec:
|
||||
// egress:
|
||||
// - hosts:
|
||||
// - "./*"
|
||||
// - "istio-system/*"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// The example below declares a `Sidecar` configuration in the
|
||||
// `prod-us1` namespace that overrides the global default defined
|
||||
// above, and configures the sidecars in the namespace to allow egress
|
||||
// traffic to public services in the `prod-us1`, `prod-apis`, and the
|
||||
// `istio-system` namespaces.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: Sidecar
|
||||
// metadata:
|
||||
// name: default
|
||||
// namespace: prod-us1
|
||||
// spec:
|
||||
// egress:
|
||||
// - hosts:
|
||||
// - "prod-us1/*"
|
||||
// - "prod-apis/*"
|
||||
// - "istio-system/*"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: Sidecar
|
||||
// metadata:
|
||||
// name: default
|
||||
// namespace: prod-us1
|
||||
// spec:
|
||||
// egress:
|
||||
// - hosts:
|
||||
// - "prod-us1/*"
|
||||
// - "prod-apis/*"
|
||||
// - "istio-system/*"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// The following example declares a `Sidecar` configuration in the
|
||||
// `prod-us1` namespace for all pods with labels `app: ratings`
|
||||
// belonging to the `ratings.prod-us1` service. The workload accepts
|
||||
// inbound HTTP traffic on port 9080. The traffic is then forwarded to
|
||||
// the attached workload instance listening on a Unix domain
|
||||
// socket. In the egress direction, in addition to the `istio-system`
|
||||
// namespace, the sidecar proxies only HTTP traffic bound for port
|
||||
// 9080 for services in the `prod-us1` namespace.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: Sidecar
|
||||
// metadata:
|
||||
// name: ratings
|
||||
// namespace: prod-us1
|
||||
// spec:
|
||||
// workloadSelector:
|
||||
// labels:
|
||||
// app: ratings
|
||||
// ingress:
|
||||
// - port:
|
||||
// number: 9080
|
||||
// protocol: HTTP
|
||||
// name: somename
|
||||
// defaultEndpoint: unix:///var/run/someuds.sock
|
||||
// egress:
|
||||
// - port:
|
||||
// number: 9080
|
||||
// protocol: HTTP
|
||||
// name: egresshttp
|
||||
// hosts:
|
||||
// - "prod-us1/*"
|
||||
// - hosts:
|
||||
// - "istio-system/*"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: Sidecar
|
||||
// metadata:
|
||||
// name: ratings
|
||||
// namespace: prod-us1
|
||||
// spec:
|
||||
// workloadSelector:
|
||||
// labels:
|
||||
// app: ratings
|
||||
// ingress:
|
||||
// - port:
|
||||
// number: 9080
|
||||
// protocol: HTTP
|
||||
// name: somename
|
||||
// defaultEndpoint: unix:///var/run/someuds.sock
|
||||
// egress:
|
||||
// - port:
|
||||
// number: 9080
|
||||
// protocol: HTTP
|
||||
// name: egresshttp
|
||||
// hosts:
|
||||
// - "prod-us1/*"
|
||||
// - hosts:
|
||||
// - "istio-system/*"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// If the workload is deployed without IPTables-based traffic capture,
|
||||
// the `Sidecar` configuration is the only way to configure the ports
|
||||
// on the proxy attached to the workload instance. The following
|
||||
// example declares a `Sidecar` configuration in the `prod-us1`
|
||||
// namespace for all pods with labels `app: productpage` belonging to
|
||||
// the `productpage.prod-us1` service. Assuming that these pods are
|
||||
// deployed without IPtable rules (i.e. the `istio-init` container)
|
||||
// and the proxy metadata `ISTIO_META_INTERCEPTION_MODE` is set to
|
||||
// `NONE`, the specification, below, allows such pods to receive HTTP
|
||||
// traffic on port 9080 (wrapped inside Istio mutual TLS) and forward
|
||||
// it to the application listening on `127.0.0.1:8080`. It also allows
|
||||
// the application to communicate with a backing MySQL database on
|
||||
// `127.0.0.1:3306`, that then gets proxied to the externally hosted
|
||||
// MySQL service at `mysql.foo.com:3306`.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: Sidecar
|
||||
// metadata:
|
||||
// name: no-ip-tables
|
||||
// namespace: prod-us1
|
||||
// spec:
|
||||
// workloadSelector:
|
||||
// labels:
|
||||
// app: productpage
|
||||
// ingress:
|
||||
// - port:
|
||||
// number: 9080 # binds to proxy_instance_ip:9080 (0.0.0.0:9080, if no unicast IP is available for the instance)
|
||||
// protocol: HTTP
|
||||
// name: somename
|
||||
// defaultEndpoint: 127.0.0.1:8080
|
||||
// captureMode: NONE # not needed if metadata is set for entire proxy
|
||||
// egress:
|
||||
// - port:
|
||||
// number: 3306
|
||||
// protocol: MYSQL
|
||||
// name: egressmysql
|
||||
// captureMode: NONE # not needed if metadata is set for entire proxy
|
||||
// bind: 127.0.0.1
|
||||
// hosts:
|
||||
// - "*/mysql.foo.com"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: Sidecar
|
||||
// metadata:
|
||||
// name: no-ip-tables
|
||||
// namespace: prod-us1
|
||||
// spec:
|
||||
// workloadSelector:
|
||||
// labels:
|
||||
// app: productpage
|
||||
// ingress:
|
||||
// - port:
|
||||
// number: 9080 # binds to proxy_instance_ip:9080 (0.0.0.0:9080, if no unicast IP is available for the instance)
|
||||
// protocol: HTTP
|
||||
// name: somename
|
||||
// defaultEndpoint: 127.0.0.1:8080
|
||||
// captureMode: NONE # not needed if metadata is set for entire proxy
|
||||
// egress:
|
||||
// - port:
|
||||
// number: 3306
|
||||
// protocol: MYSQL
|
||||
// name: egressmysql
|
||||
// captureMode: NONE # not needed if metadata is set for entire proxy
|
||||
// bind: 127.0.0.1
|
||||
// hosts:
|
||||
// - "*/mysql.foo.com"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// And the associated service entry for routing to `mysql.foo.com:3306`
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: external-svc-mysql
|
||||
// namespace: ns1
|
||||
// spec:
|
||||
// hosts:
|
||||
// - mysql.foo.com
|
||||
// ports:
|
||||
// - number: 3306
|
||||
// name: mysql
|
||||
// protocol: MYSQL
|
||||
// location: MESH_EXTERNAL
|
||||
// resolution: DNS
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: external-svc-mysql
|
||||
// namespace: ns1
|
||||
// spec:
|
||||
// hosts:
|
||||
// - mysql.foo.com
|
||||
// ports:
|
||||
// - number: 3306
|
||||
// name: mysql
|
||||
// protocol: MYSQL
|
||||
// location: MESH_EXTERNAL
|
||||
// resolution: DNS
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// It is also possible to mix and match traffic capture modes in a single
|
||||
// proxy. For example, consider a setup where internal services are on the
|
||||
// `192.168.0.0/16` subnet. So, IP tables are setup on the VM to capture all
|
||||
// outbound traffic on `192.168.0.0/16` subnet. Assume that the VM has an
|
||||
// additional network interface on `172.16.0.0/16` subnet for inbound
|
||||
// traffic. The following `Sidecar` configuration allows the VM to expose a
|
||||
// listener on `172.16.1.32:80` (the VM's IP) for traffic arriving from the
|
||||
// `172.16.0.0/16` subnet.
|
||||
//
|
||||
// **NOTE**: The `ISTIO_META_INTERCEPTION_MODE` metadata on the
|
||||
// proxy in the VM should contain `REDIRECT` or `TPROXY` as its value,
|
||||
// implying that IP tables based traffic capture is active.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: Sidecar
|
||||
// metadata:
|
||||
// name: partial-ip-tables
|
||||
// namespace: prod-us1
|
||||
// spec:
|
||||
// workloadSelector:
|
||||
// labels:
|
||||
// app: productpage
|
||||
// ingress:
|
||||
// - bind: 172.16.1.32
|
||||
// port:
|
||||
// number: 80 # binds to 172.16.1.32:80
|
||||
// protocol: HTTP
|
||||
// name: somename
|
||||
// defaultEndpoint: 127.0.0.1:8080
|
||||
// captureMode: NONE
|
||||
// egress:
|
||||
// # use the system detected defaults
|
||||
// # sets up configuration to handle outbound traffic to services
|
||||
// # in 192.168.0.0/16 subnet, based on information provided by the
|
||||
// # service registry
|
||||
// - captureMode: IPTABLES
|
||||
// hosts:
|
||||
// - "*/*"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: Sidecar
|
||||
// metadata:
|
||||
// name: partial-ip-tables
|
||||
// namespace: prod-us1
|
||||
// spec:
|
||||
// workloadSelector:
|
||||
// labels:
|
||||
// app: productpage
|
||||
// ingress:
|
||||
// - bind: 172.16.1.32
|
||||
// port:
|
||||
// number: 80 # binds to 172.16.1.32:80
|
||||
// protocol: HTTP
|
||||
// name: somename
|
||||
// defaultEndpoint: 127.0.0.1:8080
|
||||
// captureMode: NONE
|
||||
// egress:
|
||||
// # use the system detected defaults
|
||||
// # sets up configuration to handle outbound traffic to services
|
||||
// # in 192.168.0.0/16 subnet, based on information provided by the
|
||||
// # service registry
|
||||
// - captureMode: IPTABLES
|
||||
// hosts:
|
||||
// - "*/*"
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
package istio.networking.v1alpha3;
|
||||
|
||||
option go_package = "istio.io/api/networking/v1alpha3";
|
||||
|
||||
// `Sidecar` describes the configuration of the sidecar proxy that mediates
|
||||
// inbound and outbound communication of the workload instance to which it is
|
||||
// attached.
|
||||
//
|
||||
// <!-- crd generation tags
|
||||
// +cue-gen:Sidecar:groupName:networking.istio.io
|
||||
// +cue-gen:Sidecar:version:v1alpha3
|
||||
// +cue-gen:Sidecar:storageVersion
|
||||
// +cue-gen:Sidecar:annotations:helm.sh/resource-policy=keep
|
||||
// +cue-gen:Sidecar:labels:app=istio-pilot,chart=istio,heritage=Tiller,release=istio
|
||||
// +cue-gen:Sidecar:subresource:status
|
||||
// +cue-gen:Sidecar:scope:Namespaced
|
||||
// +cue-gen:Sidecar:resource:categories=istio-io,networking-istio-io
|
||||
// +cue-gen:Sidecar:preserveUnknownFields:false
|
||||
// -->
|
||||
//
|
||||
// <!-- go code generation tags
|
||||
// +kubetype-gen
|
||||
// +kubetype-gen:groupVersion=networking.istio.io/v1alpha3
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen=true
|
||||
// -->
|
||||
message Sidecar {
|
||||
// Criteria used to select the specific set of pods/VMs on which this
|
||||
// `Sidecar` configuration should be applied. If omitted, the `Sidecar`
|
||||
// configuration will be applied to all workload instances in the same namespace.
|
||||
WorkloadSelector workload_selector = 1;
|
||||
|
||||
// Ingress specifies the configuration of the sidecar for processing
|
||||
// inbound traffic to the attached workload instance. If omitted, Istio will
|
||||
// automatically configure the sidecar based on the information about the workload
|
||||
// obtained from the orchestration platform (e.g., exposed ports, services,
|
||||
// etc.). If specified, inbound ports are configured if and only if the
|
||||
// workload instance is associated with a service.
|
||||
repeated IstioIngressListener ingress = 2;
|
||||
|
||||
// Egress specifies the configuration of the sidecar for processing
|
||||
// outbound traffic from the attached workload instance to other
|
||||
// services in the mesh. If not specified, inherits the system
|
||||
// detected defaults from the namespace-wide or the global default Sidecar.
|
||||
repeated IstioEgressListener egress = 3;
|
||||
|
||||
// Configuration for the outbound traffic policy. If your
|
||||
// application uses one or more external services that are not known
|
||||
// apriori, setting the policy to `ALLOW_ANY` will cause the
|
||||
// sidecars to route any unknown traffic originating from the
|
||||
// application to its requested destination. If not specified,
|
||||
// inherits the system detected defaults from the namespace-wide or
|
||||
// the global default Sidecar.
|
||||
OutboundTrafficPolicy outbound_traffic_policy = 4;
|
||||
|
||||
reserved "localhost";
|
||||
reserved 5, 6;
|
||||
}
|
||||
|
||||
// `IstioIngressListener` specifies the properties of an inbound
|
||||
// traffic listener on the sidecar proxy attached to a workload instance.
|
||||
message IstioIngressListener {
|
||||
// The port associated with the listener.
|
||||
Port port = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// The IP to which the listener should be bound. Must be in the
|
||||
// format `x.x.x.x`. Unix domain socket addresses are not allowed in
|
||||
// the bind field for ingress listeners. If omitted, Istio will
|
||||
// automatically configure the defaults based on imported services
|
||||
// and the workload instances to which this configuration is applied
|
||||
// to.
|
||||
string bind = 2;
|
||||
|
||||
// The captureMode option dictates how traffic to the listener is
|
||||
// expected to be captured (or not).
|
||||
CaptureMode capture_mode = 3;
|
||||
|
||||
// The IP endpoint or Unix domain socket to which
|
||||
// traffic should be forwarded to. This configuration can be used to
|
||||
// redirect traffic arriving at the bind `IP:Port` on the sidecar to a `localhost:port`
|
||||
// or Unix domain socket where the application workload instance is listening for
|
||||
// connections. Arbitrary IPs are not supported. Format should be one of `127.0.0.1:PORT`, `0.0.0.0:PORT`
|
||||
// (which will forward to the instance IP), or `unix:///path/to/socket`
|
||||
string default_endpoint = 4 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
reserved "localhost_client_tls";
|
||||
reserved 5, 6;
|
||||
}
|
||||
|
||||
// `IstioEgressListener` specifies the properties of an outbound traffic
|
||||
// listener on the sidecar proxy attached to a workload instance.
|
||||
message IstioEgressListener {
|
||||
// The port associated with the listener. If using Unix domain socket,
|
||||
// use 0 as the port number, with a valid protocol. The port if
|
||||
// specified, will be used as the default destination port associated
|
||||
// with the imported hosts. If the port is omitted, Istio will infer the
|
||||
// listener ports based on the imported hosts. Note that when multiple
|
||||
// egress listeners are specified, where one or more listeners have
|
||||
// specific ports while others have no port, the hosts exposed on a
|
||||
// listener port will be based on the listener with the most specific
|
||||
// port.
|
||||
Port port = 1;
|
||||
|
||||
// The IP or the Unix domain socket to which the listener should be bound
|
||||
// to. Port MUST be specified if bind is not empty. Format: `x.x.x.x` or
|
||||
// `unix:///path/to/uds` or `unix://@foobar` (Linux abstract namespace). If
|
||||
// omitted, Istio will automatically configure the defaults based on imported
|
||||
// services, the workload instances to which this configuration is applied to and
|
||||
// the captureMode. If captureMode is `NONE`, bind will default to
|
||||
// 127.0.0.1.
|
||||
string bind = 2;
|
||||
|
||||
// When the bind address is an IP, the captureMode option dictates
|
||||
// how traffic to the listener is expected to be captured (or not).
|
||||
// captureMode must be DEFAULT or `NONE` for Unix domain socket binds.
|
||||
CaptureMode capture_mode = 3;
|
||||
|
||||
// One or more service hosts exposed by the listener
|
||||
// in `namespace/dnsName` format. Services in the specified namespace
|
||||
// matching `dnsName` will be exposed.
|
||||
// The corresponding service can be a service in the service registry
|
||||
// (e.g., a Kubernetes or cloud foundry service) or a service specified
|
||||
// using a `ServiceEntry` or `VirtualService` configuration. Any
|
||||
// associated `DestinationRule` in the same namespace will also be used.
|
||||
//
|
||||
// The `dnsName` should be specified using FQDN format, optionally including
|
||||
// a wildcard character in the left-most component (e.g., `prod/*.example.com`).
|
||||
// Set the `dnsName` to `*` to select all services from the specified namespace
|
||||
// (e.g., `prod/*`).
|
||||
//
|
||||
// The `namespace` can be set to `*`, `.`, or `~`, representing any, the current,
|
||||
// or no namespace, respectively. For example, `*/foo.example.com` selects the
|
||||
// service from any available namespace while `./foo.example.com` only selects
|
||||
// the service from the namespace of the sidecar. If a host is set to `*/*`,
|
||||
// Istio will configure the sidecar to be able to reach every service in the
|
||||
// mesh that is exported to the sidecar's namespace. The value `~/*` can be used
|
||||
// to completely trim the configuration for sidecars that simply receive traffic
|
||||
// and respond, but make no outbound connections of their own.
|
||||
//
|
||||
// NOTE: Only services and configuration artifacts exported to the sidecar's
|
||||
// namespace (e.g., `exportTo` value of `*`) can be referenced.
|
||||
// Private configurations (e.g., `exportTo` set to `.`) will
|
||||
// not be available. Refer to the `exportTo` setting in `VirtualService`,
|
||||
// `DestinationRule`, and `ServiceEntry` configurations for details.
|
||||
//
|
||||
// **WARNING:** The list of egress hosts in a `Sidecar` must also include
|
||||
// the Mixer control plane services if they are enabled. Envoy will not
|
||||
// be able to reach them otherwise. For example, add host
|
||||
// `istio-system/istio-telemetry.istio-system.svc.cluster.local` if telemetry
|
||||
// is enabled, `istio-system/istio-policy.istio-system.svc.cluster.local` if
|
||||
// policy is enabled, or add `istio-system/*` to allow all services in the
|
||||
// `istio-system` namespace. This requirement is temporary and will be removed
|
||||
// in a future Istio release.
|
||||
repeated string hosts = 4 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
reserved "localhost_server_tls";
|
||||
reserved 5, 6;
|
||||
}
|
||||
|
||||
// `WorkloadSelector` specifies the criteria used to determine if the
|
||||
// `Gateway`, `Sidecar`, or `EnvoyFilter` or `ServiceEntry`
|
||||
// configuration can be applied to a proxy. The matching criteria
|
||||
// includes the metadata associated with a proxy, workload instance
|
||||
// info such as labels attached to the pod/VM, or any other info that
|
||||
// the proxy provides to Istio during the initial handshake. If
|
||||
// multiple conditions are specified, all conditions need to match in
|
||||
// order for the workload instance to be selected. Currently, only
|
||||
// label based selection mechanism is supported.
|
||||
message WorkloadSelector {
|
||||
// One or more labels that indicate a specific set of pods/VMs
|
||||
// on which the configuration should be applied. The scope of
|
||||
// label search is restricted to the configuration namespace in which the
|
||||
// the resource is present.
|
||||
map<string, string> labels = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// $hide_from_docs
|
||||
// other forms of identification supplied by the proxy
|
||||
// when connecting to Pilot, such as X509 fields, tenant IDs, JWT,
|
||||
// etc. This has nothing to do with the request level authN etc.
|
||||
}
|
||||
|
||||
// `OutboundTrafficPolicy` sets the default behavior of the sidecar for
|
||||
// handling outbound traffic from the application.
|
||||
// If your application uses one or more external
|
||||
// services that are not known apriori, setting the policy to `ALLOW_ANY`
|
||||
// will cause the sidecars to route any unknown traffic originating from
|
||||
// the application to its requested destination. Users are strongly
|
||||
// encouraged to use `ServiceEntry` configurations to explicitly declare any external
|
||||
// dependencies, instead of using `ALLOW_ANY`, so that traffic to these
|
||||
// services can be monitored.
|
||||
message OutboundTrafficPolicy {
|
||||
enum Mode {
|
||||
// Outbound traffic will be restricted to services defined in the
|
||||
// service registry as well as those defined through `ServiceEntry` configurations.
|
||||
REGISTRY_ONLY = 0;
|
||||
// Outbound traffic to unknown destinations will be allowed, in case
|
||||
// there are no services or `ServiceEntry` configurations for the destination port.
|
||||
ALLOW_ANY = 1;
|
||||
}
|
||||
Mode mode = 1;
|
||||
|
||||
// Specifies the details of the egress proxy to which unknown
|
||||
// traffic should be forwarded to from the sidecar. Valid only if
|
||||
// the mode is set to ALLOW_ANY. If not specified when the mode is
|
||||
// ALLOW_ANY, the sidecar will send the unknown traffic directly to
|
||||
// the IP requested by the application.
|
||||
//
|
||||
// ** NOTE 1**: The specified egress host must be imported in the
|
||||
// egress section for the traffic forwarding to work.
|
||||
//
|
||||
// ** NOTE 2**: An Envoy based egress gateway is unlikely to be able
|
||||
// to handle plain text TCP connections forwarded from the sidecar.
|
||||
// Envoy's dynamic forward proxy can handle only HTTP and TLS
|
||||
// connections.
|
||||
// $hide_from_docs
|
||||
istio.networking.v1alpha3.Destination egress_proxy = 2;
|
||||
}
|
||||
|
||||
|
||||
// `CaptureMode` describes how traffic to a listener is expected to be
|
||||
// captured. Applicable only when the listener is bound to an IP.
|
||||
enum CaptureMode {
|
||||
// The default capture mode defined by the environment.
|
||||
DEFAULT = 0;
|
||||
|
||||
// Capture traffic using IPtables redirection.
|
||||
IPTABLES = 1;
|
||||
|
||||
// No traffic capture. When used in an egress listener, the application is
|
||||
// expected to explicitly communicate with the listener port or Unix
|
||||
// domain socket. When used in an ingress listener, care needs to be taken
|
||||
// to ensure that the listener port is not in use by other processes on
|
||||
// the host.
|
||||
NONE = 2;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,325 @@
|
||||
// Copyright 2020 Istio Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
import "google/api/field_behavior.proto";
|
||||
|
||||
// $schema: istio.networking.v1alpha3.WorkloadEntry
|
||||
// $title: Workload Entry
|
||||
// $description: Configuration affecting VMs onboarded into the mesh.
|
||||
// $location: https://istio.io/docs/reference/config/networking/workload-entry.html
|
||||
// $aliases: [/docs/reference/config/networking/v1alpha3/workload-entry]
|
||||
|
||||
// `WorkloadEntry` enables operators to describe the properties of a
|
||||
// single non-Kubernetes workload such as a VM or a bare metal server
|
||||
// as it is onboarded into the mesh. A `WorkloadEntry` must be
|
||||
// accompanied by an Istio `ServiceEntry` that selects the workload
|
||||
// through the appropriate labels and provides the service definition
|
||||
// for a `MESH_INTERNAL` service (hostnames, port properties, etc.). A
|
||||
// `ServiceEntry` object can select multiple workload entries as well
|
||||
// as Kubernetes pods based on the label selector specified in the
|
||||
// service entry.
|
||||
//
|
||||
// When a workload connects to `istiod`, the status field in the
|
||||
// custom resource will be updated to indicate the health of the
|
||||
// workload along with other details, similar to how Kubernetes
|
||||
// updates the status of a pod.
|
||||
//
|
||||
// The following example declares a workload entry representing a VM
|
||||
// for the `details.bookinfo.com` service. This VM has sidecar
|
||||
// installed and bootstrapped using the `details-legacy` service
|
||||
// account. The service is exposed on port 80 to applications in the
|
||||
// mesh. The HTTP traffic to this service is wrapped in Istio mutual
|
||||
// TLS and sent to sidecars on VMs on target port 8080, that in turn
|
||||
// forward it to the application on localhost on the same port.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: WorkloadEntry
|
||||
// metadata:
|
||||
// name: details-svc
|
||||
// spec:
|
||||
// # use of the service account indicates that the workload has a
|
||||
// # sidecar proxy bootstrapped with this service account. Pods with
|
||||
// # sidecars will automatically communicate with the workload using
|
||||
// # istio mutual TLS.
|
||||
// serviceAccount: details-legacy
|
||||
// address: 2.2.2.2
|
||||
// labels:
|
||||
// app: details-legacy
|
||||
// instance-id: vm1
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: WorkloadEntry
|
||||
// metadata:
|
||||
// name: details-svc
|
||||
// spec:
|
||||
// # use of the service account indicates that the workload has a
|
||||
// # sidecar proxy bootstrapped with this service account. Pods with
|
||||
// # sidecars will automatically communicate with the workload using
|
||||
// # istio mutual TLS.
|
||||
// serviceAccount: details-legacy
|
||||
// address: 2.2.2.2
|
||||
// labels:
|
||||
// app: details-legacy
|
||||
// instance-id: vm1
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// and the associated service entry
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: details-svc
|
||||
// spec:
|
||||
// hosts:
|
||||
// - details.bookinfo.com
|
||||
// location: MESH_INTERNAL
|
||||
// ports:
|
||||
// - number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// targetPort: 8080
|
||||
// resolution: STATIC
|
||||
// workloadSelector:
|
||||
// labels:
|
||||
// app: details-legacy
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: details-svc
|
||||
// spec:
|
||||
// hosts:
|
||||
// - details.bookinfo.com
|
||||
// location: MESH_INTERNAL
|
||||
// ports:
|
||||
// - number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// targetPort: 8080
|
||||
// resolution: STATIC
|
||||
// workloadSelector:
|
||||
// labels:
|
||||
// app: details-legacy
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
//
|
||||
// The following example declares the same VM workload using
|
||||
// its fully qualified DNS name. The service entry's resolution
|
||||
// mode should be changed to DNS to indicate that the client-side
|
||||
// sidecars should dynamically resolve the DNS name at runtime before
|
||||
// forwarding the request.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: WorkloadEntry
|
||||
// metadata:
|
||||
// name: details-svc
|
||||
// spec:
|
||||
// # use of the service account indicates that the workload has a
|
||||
// # sidecar proxy bootstrapped with this service account. Pods with
|
||||
// # sidecars will automatically communicate with the workload using
|
||||
// # istio mutual TLS.
|
||||
// serviceAccount: details-legacy
|
||||
// address: vm1.vpc01.corp.net
|
||||
// labels:
|
||||
// app: details-legacy
|
||||
// instance-id: vm1
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: WorkloadEntry
|
||||
// metadata:
|
||||
// name: details-svc
|
||||
// spec:
|
||||
// # use of the service account indicates that the workload has a
|
||||
// # sidecar proxy bootstrapped with this service account. Pods with
|
||||
// # sidecars will automatically communicate with the workload using
|
||||
// # istio mutual TLS.
|
||||
// serviceAccount: details-legacy
|
||||
// address: vm1.vpc01.corp.net
|
||||
// labels:
|
||||
// app: details-legacy
|
||||
// instance-id: vm1
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
// and the associated service entry
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: details-svc
|
||||
// spec:
|
||||
// hosts:
|
||||
// - details.bookinfo.com
|
||||
// location: MESH_INTERNAL
|
||||
// ports:
|
||||
// - number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// targetPort: 8080
|
||||
// resolution: DNS
|
||||
// workloadSelector:
|
||||
// labels:
|
||||
// app: details-legacy
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
//
|
||||
// {{<tab name="v1beta1" category-value="v1beta1">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1beta1
|
||||
// kind: ServiceEntry
|
||||
// metadata:
|
||||
// name: details-svc
|
||||
// spec:
|
||||
// hosts:
|
||||
// - details.bookinfo.com
|
||||
// location: MESH_INTERNAL
|
||||
// ports:
|
||||
// - number: 80
|
||||
// name: http
|
||||
// protocol: HTTP
|
||||
// targetPort: 8080
|
||||
// resolution: DNS
|
||||
// workloadSelector:
|
||||
// labels:
|
||||
// app: details-legacy
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
package istio.networking.v1alpha3;
|
||||
|
||||
option go_package = "istio.io/api/networking/v1alpha3";
|
||||
|
||||
// WorkloadEntry enables specifying the properties of a single non-Kubernetes workload such a VM or a bare metal services that can be referred to by service entries.
|
||||
//
|
||||
// <!-- crd generation tags
|
||||
// +cue-gen:WorkloadEntry:groupName:networking.istio.io
|
||||
// +cue-gen:WorkloadEntry:version:v1alpha3
|
||||
// +cue-gen:WorkloadEntry:storageVersion
|
||||
// +cue-gen:WorkloadEntry:annotations:helm.sh/resource-policy=keep
|
||||
// +cue-gen:WorkloadEntry:labels:app=istio-pilot,chart=istio,heritage=Tiller,release=istio
|
||||
// +cue-gen:WorkloadEntry:subresource:status
|
||||
// +cue-gen:WorkloadEntry:scope:Namespaced
|
||||
// +cue-gen:WorkloadEntry:resource:categories=istio-io,networking-istio-io,shortNames=we,plural=workloadentries
|
||||
// +cue-gen:WorkloadEntry:printerColumn:name=Age,type=date,JSONPath=.metadata.creationTimestamp,description="CreationTimestamp is a timestamp
|
||||
// representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations.
|
||||
// Clients may not set this value. It is represented in RFC3339 form and is in UTC.
|
||||
// Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"
|
||||
// +cue-gen:WorkloadEntry:printerColumn:name=Address,type=string,JSONPath=.spec.address,description="Address associated with the network endpoint."
|
||||
// +cue-gen:WorkloadEntry:preserveUnknownFields:false
|
||||
// -->
|
||||
//
|
||||
// <!-- go code generation tags
|
||||
// +kubetype-gen
|
||||
// +kubetype-gen:groupVersion=networking.istio.io/v1alpha3
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen=true
|
||||
// -->
|
||||
message WorkloadEntry {
|
||||
// Address associated with the network endpoint without the
|
||||
// port. Domain names can be used if and only if the resolution is set
|
||||
// to DNS, and must be fully-qualified without wildcards. Use the form
|
||||
// unix:///absolute/path/to/socket for Unix domain socket endpoints.
|
||||
string address = 1 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// Set of ports associated with the endpoint. If the port map is
|
||||
// specified, it must be a map of servicePortName to this endpoint's
|
||||
// port, such that traffic to the service port will be forwarded to
|
||||
// the endpoint port that maps to the service's portName. If
|
||||
// omitted, and the targetPort is specified as part of the service's
|
||||
// port specification, traffic to the service port will be forwarded
|
||||
// to one of the endpoints on the specified `targetPort`. If both
|
||||
// the targetPort and endpoint's port map are not specified, traffic
|
||||
// to a service port will be forwarded to one of the endpoints on
|
||||
// the same port.
|
||||
//
|
||||
// **NOTE 1:** Do not use for `unix://` addresses.
|
||||
//
|
||||
// **NOTE 2:** endpoint port map takes precedence over targetPort.
|
||||
map<string, uint32> ports = 2;
|
||||
|
||||
// One or more labels associated with the endpoint.
|
||||
map<string, string> labels = 3;
|
||||
|
||||
// Network enables Istio to group endpoints resident in the same L3
|
||||
// domain/network. All endpoints in the same network are assumed to be
|
||||
// directly reachable from one another. When endpoints in different
|
||||
// networks cannot reach each other directly, an Istio Gateway can be
|
||||
// used to establish connectivity (usually using the
|
||||
// `AUTO_PASSTHROUGH` mode in a Gateway Server). This is
|
||||
// an advanced configuration used typically for spanning an Istio mesh
|
||||
// over multiple clusters.
|
||||
string network = 4;
|
||||
|
||||
// The locality associated with the endpoint. A locality corresponds
|
||||
// to a failure domain (e.g., country/region/zone). Arbitrary failure
|
||||
// domain hierarchies can be represented by separating each
|
||||
// encapsulating failure domain by /. For example, the locality of an
|
||||
// an endpoint in US, in US-East-1 region, within availability zone
|
||||
// az-1, in data center rack r11 can be represented as
|
||||
// us/us-east-1/az-1/r11. Istio will configure the sidecar to route to
|
||||
// endpoints within the same locality as the sidecar. If none of the
|
||||
// endpoints in the locality are available, endpoints parent locality
|
||||
// (but within the same network ID) will be chosen. For example, if
|
||||
// there are two endpoints in same network (networkID "n1"), say e1
|
||||
// with locality us/us-east-1/az-1/r11 and e2 with locality
|
||||
// us/us-east-1/az-2/r12, a sidecar from us/us-east-1/az-1/r11 locality
|
||||
// will prefer e1 from the same locality over e2 from a different
|
||||
// locality. Endpoint e2 could be the IP associated with a gateway
|
||||
// (that bridges networks n1 and n2), or the IP associated with a
|
||||
// standard service endpoint.
|
||||
string locality = 5;
|
||||
|
||||
// The load balancing weight associated with the endpoint. Endpoints
|
||||
// with higher weights will receive proportionally higher traffic.
|
||||
uint32 weight = 6;
|
||||
|
||||
// The service account associated with the workload if a sidecar
|
||||
// is present in the workload. The service account must be present
|
||||
// in the same namespace as the configuration ( WorkloadEntry or a
|
||||
// ServiceEntry)
|
||||
string service_account = 7;
|
||||
};
|
||||
|
||||
@ -0,0 +1,206 @@
|
||||
// Copyright 2020 Istio Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
import "google/api/field_behavior.proto";
|
||||
import "networking/v1alpha3/workload_entry.proto";
|
||||
|
||||
// $schema: istio.networking.v1alpha3.WorkloadGroup
|
||||
// $title: Workload Group
|
||||
// $description: Describes a collection of workload instances.
|
||||
// $location: https://istio.io/docs/reference/config/networking/workload-group.html
|
||||
// $aliases: [/docs/reference/config/networking/v1alpha3/workload-group]
|
||||
|
||||
// `WorkloadGroup` describes a collection of workload instances.
|
||||
// It provides a specification that the workload instances can use to bootstrap
|
||||
// their proxies, including the metadata and identity. It is only intended to
|
||||
// be used with non-k8s workloads like Virtual Machines, and is meant to mimic
|
||||
// the existing sidecar injection and deployment specification model used for
|
||||
// Kubernetes workloads to bootstrap Istio proxies.
|
||||
//
|
||||
// The following example declares a workload group representing a collection
|
||||
// of workloads that will be registered under `reviews` in namespace
|
||||
// `bookinfo`. The set of labels will be associated with each workload
|
||||
// instance during the bootstrap process, and the ports 3550 and 8080
|
||||
// will be associated with the workload group and use service account `default`.
|
||||
// `app.kubernetes.io/version` is just an arbitrary example of a label.
|
||||
//
|
||||
// {{<tabset category-name="example">}}
|
||||
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
|
||||
// ```yaml
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: WorkloadGroup
|
||||
// metadata:
|
||||
// name: reviews
|
||||
// namespace: bookinfo
|
||||
// spec:
|
||||
// metadata:
|
||||
// labels:
|
||||
// app.kubernetes.io/name: reviews
|
||||
// app.kubernetes.io/version: "1.3.4"
|
||||
// template:
|
||||
// ports:
|
||||
// grpc: 3550
|
||||
// http: 8080
|
||||
// serviceAccount: default
|
||||
// probe:
|
||||
// initialDelaySeconds: 5
|
||||
// timeoutSeconds: 3
|
||||
// periodSeconds: 4
|
||||
// successThreshold: 3
|
||||
// failureThreshold: 3
|
||||
// httpGet:
|
||||
// path: /foo/bar
|
||||
// host: 127.0.0.1
|
||||
// port: 3100
|
||||
// scheme: https
|
||||
// httpHeaders:
|
||||
// - name: Lit-Header
|
||||
// value: Im-The-Best
|
||||
// ```
|
||||
// {{</tab>}}
|
||||
// {{</tabset>}}
|
||||
//
|
||||
package istio.networking.v1alpha3;
|
||||
|
||||
option go_package = "istio.io/api/networking/v1alpha3";
|
||||
|
||||
// `WorkloadGroup` enables specifying the properties of a single workload for bootstrap and
|
||||
// provides a template for `WorkloadEntry`, similar to how `Deployment` specifies properties
|
||||
// of workloads via `Pod` templates. A `WorkloadGroup` can have more than one `WorkloadEntry`.
|
||||
// `WorkloadGroup` has no relationship to resources which control service registry like `ServiceEntry`
|
||||
// and as such doesn't configure host name for these workloads.
|
||||
//
|
||||
// <!-- crd generation tags
|
||||
// +cue-gen:WorkloadGroup:groupName:networking.istio.io
|
||||
// +cue-gen:WorkloadGroup:version:v1alpha3
|
||||
// +cue-gen:WorkloadGroup:storageVersion
|
||||
// +cue-gen:WorkloadGroup:subresource:status
|
||||
// +cue-gen:WorkloadGroup:scope:Namespaced
|
||||
// +cue-gen:WorkloadGroup:resource:categories=istio-io,networking-istio-io,shortNames=wg,plural=workloadgroups
|
||||
// +cue-gen:WorkloadGroup:printerColumn:name=Age,type=date,JSONPath=.metadata.creationTimestamp,description="CreationTimestamp is a timestamp
|
||||
// representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations.
|
||||
// Clients may not set this value. It is represented in RFC3339 form and is in UTC.
|
||||
// Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"
|
||||
// +cue-gen:WorkloadGroup:preserveUnknownFields:false
|
||||
// -->
|
||||
//
|
||||
// <!-- go code generation tags
|
||||
// +kubetype-gen
|
||||
// +kubetype-gen:groupVersion=networking.istio.io/v1alpha3
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen=true
|
||||
// -->
|
||||
message WorkloadGroup {
|
||||
// Metadata that will be used for all corresponding `WorkloadEntries`.
|
||||
// User labels for a workload group should be set here in `metadata` rather than in `template`.
|
||||
ObjectMeta metadata = 1;
|
||||
|
||||
// Template to be used for the generation of `WorkloadEntry` resources that belong to this `WorkloadGroup`.
|
||||
// Please note that `address` and `labels` fields should not be set in the template, and an empty `serviceAccount`
|
||||
// should default to `default`. The workload identities (mTLS certificates) will be bootstrapped using the
|
||||
// specified service account's token. Workload entries in this group will be in the same namespace as the
|
||||
// workload group, and inherit the labels and annotations from the above `metadata` field.
|
||||
WorkloadEntry template = 2 [(google.api.field_behavior) = REQUIRED];
|
||||
|
||||
// `ObjectMeta` describes metadata that will be attached to a `WorkloadEntry`.
|
||||
// It is a subset of the supported Kubernetes metadata.
|
||||
message ObjectMeta {
|
||||
// Labels to attach
|
||||
map<string, string> labels = 1;
|
||||
|
||||
// Annotations to attach
|
||||
map<string, string> annotations = 2;
|
||||
}
|
||||
|
||||
// `ReadinessProbe` describes the configuration the user must provide for healthchecking on their workload.
|
||||
// This configuration mirrors K8S in both syntax and logic for the most part.
|
||||
ReadinessProbe probe = 3;
|
||||
}
|
||||
|
||||
message ReadinessProbe {
|
||||
|
||||
// Number of seconds after the container has started before readiness probes are initiated.
|
||||
int32 initial_delay_seconds = 2;
|
||||
|
||||
// Number of seconds after which the probe times out.
|
||||
// Defaults to 1 second. Minimum value is 1 second.
|
||||
int32 timeout_seconds = 3;
|
||||
|
||||
// How often (in seconds) to perform the probe.
|
||||
// Default to 10 seconds. Minimum value is 1 second.
|
||||
int32 period_seconds = 4;
|
||||
|
||||
// Minimum consecutive successes for the probe to be considered successful after having failed.
|
||||
// Defaults to 1 second.
|
||||
int32 success_threshold = 5;
|
||||
|
||||
// Minimum consecutive failures for the probe to be considered failed after having succeeded.
|
||||
// Defaults to 3 seconds.
|
||||
int32 failure_threshold = 6;
|
||||
|
||||
// Users can only provide one configuration for healthchecks (tcp, http, exec),
|
||||
// and this is expressed as a oneof. All of the other configuration values
|
||||
// hold true for any of the healthcheck methods.
|
||||
oneof health_check_method {
|
||||
// `httpGet` is performed to a given endpoint
|
||||
// and the status/able to connect determines health.
|
||||
HTTPHealthCheckConfig http_get = 7;
|
||||
// Health is determined by if the proxy is able to connect.
|
||||
TCPHealthCheckConfig tcp_socket = 8;
|
||||
// Health is determined by how the command that is executed exited.
|
||||
ExecHealthCheckConfig exec = 9;
|
||||
}
|
||||
}
|
||||
|
||||
message HTTPHealthCheckConfig {
|
||||
// Path to access on the HTTP server.
|
||||
string path = 1;
|
||||
|
||||
// Port on which the endpoint lives.
|
||||
uint32 port = 2;
|
||||
|
||||
// Host name to connect to, defaults to the pod IP. You probably want to set
|
||||
// "Host" in httpHeaders instead.
|
||||
string host = 3;
|
||||
|
||||
// HTTP or HTTPS, defaults to HTTP
|
||||
string scheme = 4;
|
||||
|
||||
// Headers the proxy will pass on to make the request.
|
||||
// Allows repeated headers.
|
||||
repeated HTTPHeader http_headers = 5;
|
||||
}
|
||||
|
||||
message HTTPHeader {
|
||||
// The header field name
|
||||
string name = 1;
|
||||
|
||||
// The header field value
|
||||
string value = 2;
|
||||
}
|
||||
|
||||
message TCPHealthCheckConfig {
|
||||
// Host to connect to, defaults to localhost
|
||||
string host = 1;
|
||||
// Port of host
|
||||
uint32 port = 2;
|
||||
}
|
||||
|
||||
message ExecHealthCheckConfig {
|
||||
// Command to run. Exit status of 0 is treated as live/healthy and non-zero is unhealthy.
|
||||
repeated string command = 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user